Excel檔案 利用MySQL/Python 實現自動處理資料的功能

酸菜魚土豆大俠發表於2023-02-21

問題描述:

在沒有伺服器儲存資料,只有excel檔案的情況下,如何利用SQL和python實現資料分析和資料自動處理的功能?

例如:消費者購買商品時,會挑選商品然後再對商品付款。現在需要查詢出使用者挑中但是沒有付款的商品並標識為未下單,付款的商品標註為下單。並且每隔一段時間自動執行上述操作。

目的:定時抽取上面的資料分析使用者購買商品的行為。對比付款和選中未下單的商品的效能、價格等資訊來發掘使用者喜好,從而提高選品下單率。

注意:

  • 使用者的資訊主要以excel的形式儲存,沒有伺服器。
  • 商品表裡面存了使用者挑選的商品資訊。
  • 訂單表裡面存了使用者付款的商品資訊。

解決方案:

一、SQL查詢

首先想到的是利用SQL語言實現這樣的查詢。具體實現過程如下:

(1) 建立dingdan表和shangpin表:

-- ----------------------------
-- Table structure for dingdan
-- ----------------------------
DROP TABLE IF EXISTS `dingdan`;
CREATE TABLE `dingdan`  (
  `d_id` int(11) NOT NULL,
  `UPC` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`d_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of dingdan
-- ----------------------------
INSERT INTO `dingdan` VALUES (1, '6972470560664');
INSERT INTO `dingdan` VALUES (2, '6972470560664');
INSERT INTO `dingdan` VALUES (3, '6972470561227');
INSERT INTO `dingdan` VALUES (4, '6972470561890');
INSERT INTO `dingdan` VALUES (5, '6972470561906');

SET FOREIGN_KEY_CHECKS = 1;


-- ----------------------------
-- Table structure for shangpin
-- ----------------------------
DROP TABLE IF EXISTS `shangpin`;
CREATE TABLE `shangpin`  (
  `UPC` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `商品` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`UPC`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of shangpin
-- ----------------------------
INSERT INTO `shangpin` VALUES ('6972470560657', 'A');
INSERT INTO `shangpin` VALUES ('6972470560664', 'A');
INSERT INTO `shangpin` VALUES ('6972470561210', 'D');
INSERT INTO `shangpin` VALUES ('6972470561227', 'B');
INSERT INTO `shangpin` VALUES ('6972470561890', 'C');
INSERT INTO `shangpin` VALUES ('6972470651791', 'B');

SET FOREIGN_KEY_CHECKS = 1;


(2) 將excel資料匯入SQL軟體中。

  • 執行下面的查詢語句進行查詢:
-- 搜尋未下單的商品資訊
SELECT *,
if(bb.UPC IS NULL,'未下單', '下單') as 下單情況

FROM shangpin aa

LEFT JOIN dingdan bb
ON aa.UPC = bb.UPC
  • 得到以下查詢結果:

(3) 將搜尋結果匯出為excel。

(4) 隔一段時間,需要人工重複上面的操作。

二、SQL、python處理

利用SQL查詢、python做定時處理。具體實現過程如下:

(1) 重複方案1中的步驟1和2,將資料匯入到資料庫中。

(2) 用python連線資料庫並查詢資料。

import pymysql  #匯入PyMySQL庫 
import datetime
import warnings
import pandas as pd
import matplotlib.pyplot as plt
warnings.filterwarnings('ignore')

# 1. 連線資料庫,建立連線物件 db
# 連線物件作用是:連線資料庫、傳送資料庫資訊、處理回滾操作(查詢中斷時,資料庫回到最初狀態)、
# 建立新的游標物件 
def connect_database(database, password):
     db = pymysql.connect(host ="localhost", #host屬性 
                              user ="sys", #使用者名稱  
                              password = password, #此處填登入資料庫的密碼 
                              database = database, #資料庫名 
                              charset="utf8"  # 如果中文顯示亂碼,則需要新增charset = "utf8"
                         )
     return db

def read_data(db):
     # 2. 使用 cursor() 方法建立一個遊標物件 cursor
     cursor = db.cursor()
     # 3. 利用MySQL語句查詢資料並轉化為FrameData(包含列名)
     try:
          # 使用 execute() 方法執行 SQL 查詢
          mysql = "SELECT *, if(bb.UPC IS NULL,'未下單', '下單') as 下單情況 FROM shangpin aa LEFT JOIN dingdan bb ON aa.UPC = bb.UPC" # SQL語句
          cursor.execute(mysql)
          data = cursor.fetchall()

          # 下面為將獲取的資料轉化為 dataframe 格式
          columnDes = cursor.description #獲取連線物件的描述資訊
          #print("cursor.description中的內容:",columnDes)
          columnNames = [columnDes[i][0] for i in range(len(columnDes))] #獲取列名
          df = pd.DataFrame([list(i) for i in data],columns=columnNames) #得到的data為二維元組,逐行取出,轉化為列表,再轉化為df
          print(df)

          """
          db.commit()若對資料庫進行了修改,需進行提交之後再關閉
          """
          # 提交到資料庫執行
          #db.commit()
          #print("OK")
     except:
          # 如果發生錯誤則回滾
          db.rollback()
          print("失敗")
     """
     使用完成之後需關閉遊標和資料庫連線,減少資源佔用,cursor.close(),db.close()
     db.commit()若對資料庫進行了修改,需進行提交之後再關閉
     """
     # 關閉資料庫連線
     cursor.close()
     db.close()
     return df    

(3) 做定時任務

     ## 定時任務
     import time
     from apscheduler.schedulers.blocking import BlockingScheduler
     
     def job():
       dt = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
       print('{} --- {}'.format(text, t))
       database = 'sys' #資料庫名稱
       password = 'sys' #資料庫使用者密碼
       db = connect_database(database, password)
       data_sp = read_data(db)
       data_sp.to_excel('../data/data_ans.xlsx', sheet_name='未下單情況')
       
     scheduler = BlockingScheduler()
     # 在每天22和23點的25分,執行一次 job 方法
     scheduler.add_job(job, 'cron', hour='22-23', minute='25')
     scheduler.start()
     
     ## 測試
     # 執行任務
     def time_printer():
         # 輸出時間
         now = datetime.datetime.now()
         ts = now.strftime('%Y-%m-%d %H:%M:%S')
         print('do func time :', ts)
     # 定時任務
     def loop_monitor():
         while True:
             time.sleep(20)  # 暫停20秒
             
     if __name__ == "__main__":
         loop_monitor()
  • 開啟data_ans的excel檔案即可檢視資料。

  • 程式需要一直執行,如果因為關機導致程式終止,需要重新執行。

三、python處理

python處理。具體實現過程如下:

(1) 匯入excel資料並利用python完成資料查詢,以excel的形式匯出查詢好的資料。

參考

import pandas as pd
def taskTime():
## 1. 分別匯入2個表的資料
    product = pd.read_excel('d:/python_code/crontab/data/taskdata.xlsx', sheet_name='商品') # 換成自己的路徑和sheet名稱
    order = pd.read_excel('d:/python_code/crontab/data/taskdata.xlsx', sheet_name='訂單') 

    ## 2. 抽取資料
    product=product.rename(columns={'UPC':'ID'}) # 對商品表裡面的UPC重新命名未ID(為了保留訂單表裡面的CPU著一列)
    PO=pd.merge(product,order,left_on='ID', right_on='UPC',how='left') # 左連線抽取資料
    PO.loc[pd.isnull(PO['UPC']), '下單情況'] = '未下單' # 找到選中但是未下單的資料標註為未下單
    PO['下單情況'] = PO['下單情況'].fillna(value='下單') # 找到下單的資料,在'下單情況'這一列中標註為下單

    ## 3. 以excel的形式匯出查詢好的資料
    PO = PO.loc[:, ['ID', 'UPC', '下單情況', '產品名稱E', '產品引數C', '價格', '建議零售價','訂單日期', '品牌', 'PO#', 'SKU','配置', '單價', '數量', '銷售金額', '成本單價', '成本', '成本價含稅/未稅']] # 按列名匯出需要的資料
    PO.to_excel('d:/python_code/crontab/data/data_python.xlsx', sheet_name='未下單情況')  # 匯出excel表
    return PO

if __name__ == "__main__":
  taskTime()
    print('執行成功')

(2) 定時處理

   ## 2. 定時處理
   import datetime
   from apscheduler.schedulers.blocking import BlockingScheduler
   
   def job():
     now = datetime.datetime.now()
     ts = now.strftime('%Y-%m-%d %H:%M:%S')
     print('執行時間 :', ts)   # 輸出時間
     taskTime()  # 執行程式碼
   
   scheduler = BlockingScheduler() ## 定時 
   # 在每天17和23點的25分,執行一次 job 方法
 scheduler.add_job(job, 'cron', hour='17-23', minute='22')
   scheduler.start()
  • 開啟data_python的excel檔案即可檢視資料。

  • 程式需要一直執行,如果因為關機導致程式終止,需要重新執行。

四、最佳化python處理

1.手動執行程式碼

如果電腦需要關機,這時候程式碼不能一直執行,只能在需要資料的時候執行一下程式碼。有以下2個執行方法:

(1)用命令列執行程式碼,具體操作如下:

  • win + R 輸入cmd 再輸入 路徑以及檔名

    python d:\python_code\crontab\code\test.py
    

    見下圖

  • 注意:資料還有程式碼的路徑要寫對

  • 如果不想用命令列。直接用.bat檔案執行也可以。

    • 首先,需要新建一個.bat檔案(用來執行指令碼),在這個檔案裡面寫上如下程式碼後儲存:

       python 路徑\檔名.py
      

  • 將這個檔案放到桌面,使用時點選即可。

2.開機自動執行程式碼

參考

  • 將已經儲存的.bat檔案複製到該目錄(C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup)下,可能防毒軟體會阻止,選擇允許,然後重啟電腦即可。

    注:開機自啟以後會開啟一個cmd視窗,關閉視窗,python程式將停止執行。

  • 注意:開啟自啟動可能會讓電腦變慢、發熱。。。

對比四種方案:

方案名稱 優點 缺點
SQL查詢 程式碼簡單,實現簡單 資料一旦更新需要執行匯入匯出excel的操作。並且需要手動操作,不能自動提醒。
SQL、python處理 避免匯出excel;可以自動提醒 還是需要匯入excel;同時操作SQL和python;自動提醒需要程式一直執行
python處理 避免匯入匯出;可以自動提醒,只操作python 查詢時的處理不好做(對新手來說);自動提醒需要程式一直執行
最佳化python處理 避免匯入匯出;自動提醒不需要程式一直執行,開機自啟動 需要配置一下

總結:

在沒有伺服器,以excel儲存資料的情況下,同樣可以利用SQL和python來做資料處理和分析,在遇到excel處理資料特別麻煩的時候可以選擇上面的方案做處理,即可以鍛鍊自己的SQL和python程式設計的能力,又可以高效地解決問題。

相關文章