无法运行似乎对其他人有用的MySQL代码

时间:2019-04-14 21:21:41

标签: mysql sql mysql-workbench

代码的目标是选择月,SaleID,总计和增长。我可以显示Month,SaleID和Total,但无法正常使用Growth,因为它总是从第一行开始计算。我在做什么错了?

我尝试设置变量,模拟LAG(),PREV,CURRENT,NEXT以获取计算应使用的行,但不会注册本机函数。

CREATE VIEW SalesTemp
    AS
        SELECT 
            DATE_FORMAT(Sales.SaleDate, "%Y-%m") AS Month,
            Sales.SaleID,
            Sales.Total
        FROM Sales
        WHERE SaleDate BETWEEN '2018-04-00' AND '2040-00-00' 
        GROUP BY DATE_FORMAT(Sales.SaleDate, "%Y-%m"); 

SELECT * FROM SalesTemp;

DROP VIEW IF EXISTS PercentageGrowth;
CREATE VIEW PercentageGrowth 
    AS
        SELECT 
            DATE_FORMAT(Sales.SaleDate, "%Y-%m") AS Month,
            Sales.SaleID,
            Sales.Total,
            CONCAT(ROUND(((Sales.Total) - SalesTemp.Total) / (SELECT SalesTemp.Total FROM SalesTemp GROUP BY DATE_FORMAT(SalesTemp.Month, "%Y-%m")) * 100, 2), "%") AS Growth
        FROM Sales, SalesTemp
        GROUP BY DATE_FORMAT(Sales.SaleDate, "%Y-%m");

SELECT * FROM PercentageGrowth;

DROP VIEW PercentageGrowth;
DROP VIEW SalesTemp;

我希望它通过((newValue-oldValue)/ oldValue)的计算来显示公司的成长。

因为我无法链接图片,所以我会给出结果。我现在从SELECT中得到的是:

+--------------------------------------+
|  Month  | SaleID |  Total  | Growth  |
| ------- | ------ | ------- | ------- |
| 2018-04 |    1   | 310.46  | 00.00%  |
| 2018-05 |    3   | 2160.62 | 595.54% |
| 2018-06 |    6   | 1087.89 | 250.21% |
| 2018-07 |    14  | 2314.54 | 645.09% |
+--------------------------------------+

我要说:

+--------------------------------------+
|  Month  | SaleID |  Total  | Growth  |
| ------- | ------ | ------- | ------- |
| 2018-04 |    1   | 310.46  | 00.00%  |
| 2018-05 |    3   | 2160.62 | 595.54% |
| 2018-06 |    6   | 1087.89 | -49.64% |
| 2018-07 |    14  | 2314.54 | 112.76% |
+--------------------------------------+

1 个答案:

答案 0 :(得分:0)

当前,您正在跨所有 SaleID 和所有格式化日期月份交叉连接表配对,这又由于不清楚的聚合而进一步受到影响。

假设您使用的是MySQL 8+,请考虑几个CTE,其中包括 import 'package:flutter/material.dart'; import 'dart:async'; import 'dart:convert'; import 'package:flutter_easyrefresh/easy_refresh.dart'; import 'package:http/http.dart' as http; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, backgroundColor: Colors.white ), home: DuelLeaderBoards(), ); } } class DuelLeaderBoards extends StatefulWidget { @override _DuelLeaderBoardsState createState() => _DuelLeaderBoardsState(); } class _DuelLeaderBoardsState extends State<DuelLeaderBoards> { List<Entry> str = []; GlobalKey<EasyRefreshState> _easyRefreshKey = new GlobalKey<EasyRefreshState>(); GlobalKey<RefreshHeaderState> _headerKey = new GlobalKey<RefreshHeaderState>(); GlobalKey<RefreshHeaderState> _connectorHeaderKey = new GlobalKey<RefreshHeaderState>(); GlobalKey<RefreshFooterState> _footerKey = new GlobalKey<RefreshFooterState>(); GlobalKey<RefreshFooterState> _connectorFooterKey = new GlobalKey<RefreshFooterState>(); Future<LeaderBoards> getLeaderBoards(start) async { String apiURL = 'https://stats.quake.com/api/v2/Leaderboard?from=$start&board=duel&season=current'; final response = await http.get(apiURL); if (response.statusCode == 200) { final responseBody = leaderBoardsFromJson(response.body); return responseBody; } else { throw Exception('Failed to load Data'); } } void updateLeaderBoardList(e) async { setState(() { str.addAll(e.entries); }); } @override void initState() { getLeaderBoards(0).then((onValue) => str = onValue.entries ); super.initState(); } @override Widget build(BuildContext context) { Widget header = ClassicsHeader( key: _headerKey, refreshText: "pullToRefresh", refreshReadyText: "releaseToRefresh", refreshingText: "refreshing...", refreshedText: "refreshed", moreInfo: "updateAt", bgColor: Colors.transparent, textColor: Colors.white, ); Widget footer = ClassicsFooter( key: _footerKey, loadHeight: 50.0, loadText: "pushToLoad", loadReadyText: "releaseToLoad", loadingText: "loading", loadedText: "loaded", noMoreText: "Finished", moreInfo: "updateAt", bgColor: Colors.transparent, textColor: Colors.white, ); return FutureBuilder( future: getLeaderBoards(0), builder: (BuildContext context, AsyncSnapshot<LeaderBoards> snapshot) { if (!snapshot.hasData) { return Center( child: CircularProgressIndicator(), ); } else { return Builder(builder: (BuildContext context) { return Center( child: new EasyRefresh( key: _easyRefreshKey, behavior: ScrollOverBehavior(), refreshHeader: ConnectorHeader( key: _connectorHeaderKey, header: header, ), refreshFooter: ConnectorFooter( key: _connectorFooterKey, footer: footer, ), child: CustomScrollView( semanticChildCount: str.length, slivers: <Widget>[ SliverList( delegate: SliverChildListDelegate(<Widget>[header]), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) { return new Container( height: 70.0, child: Card( child: new Text( '${index+1}: ${str[index].userName}', style: new TextStyle(fontSize: 18.0), ), )); }, childCount: str.length, )), SliverList( delegate: SliverChildListDelegate(<Widget>[footer]), ) ], ), onRefresh: () async { await new Future.delayed(const Duration(seconds: 0), () { setState(() {}); }); }, loadMore: () async { getLeaderBoards(str.length).then((onValue) => { updateLeaderBoardList(onValue) }); }, // loadMore: () async { // await new Future.delayed(const Duration(seconds: 0), () { // getLeaderBoards(str.length).then((onValue) => { // updateLeaderBoardList(onValue) // }); // }); // }, ) ); }); } }); } } LeaderBoards leaderBoardsFromJson(String str) { final jsonData = json.decode(str); return LeaderBoards.fromJson(jsonData); } String leaderBoardsToJson(LeaderBoards data) { final dyn = data.toJson(); return json.encode(dyn); } class LeaderBoards { String boardType; List<Entry> entries; int totalEntries; LeaderBoards({ this.boardType, this.entries, this.totalEntries, }); factory LeaderBoards.fromJson(Map<String, dynamic> json) => new LeaderBoards( boardType: json["boardType"] == null ? null : json["boardType"], entries: json["entries"] == null ? null : new List<Entry>.from(json["entries"].map((x) => Entry.fromJson(x))), totalEntries: json["totalEntries"] == null ? null : json["totalEntries"], ); Map<String, dynamic> toJson() => { "boardType": boardType == null ? null : boardType, "entries": entries == null ? null : new List<dynamic>.from(entries.map((x) => x.toJson())), "totalEntries": totalEntries == null ? null : totalEntries, }; } class Entry { String userName; int eloRating; String profileIconId; String namePlateId; Entry({ this.userName, this.eloRating, this.profileIconId, this.namePlateId, }); factory Entry.fromJson(Map<String, dynamic> json) => new Entry( userName: json["userName"] == null ? null : json["userName"], eloRating: json["eloRating"] == null ? null : json["eloRating"], profileIconId: json["profileIconId"] == null ? null : json["profileIconId"], namePlateId: json["namePlateId"] == null ? null : json["namePlateId"], ); Map<String, dynamic> toJson() => { "userName": userName == null ? null : userName, "eloRating": eloRating == null ? null : eloRating, "profileIconId": profileIconId == null ? null : profileIconId, "namePlateId": namePlateId == null ? null : namePlateId, }; } ,相差一个月的总计:

LAG

对于MySQL 5.7或更低版​​本,请考虑子查询的自联接,该子查询显式联接 SaleID 和上个月中的任何日期,以将所有日期标准化为各自月的第一个月。

WITH cte1 AS 
  (SELECT DATE_FORMAT(Sales.SaleDate, "%Y-%m") AS `Month`,
          Sales.SaleID,
          SUM(Sales.Total) AS `Total_Sales`
   FROM Sales
   WHERE SaleDate BETWEEN '2018-04-00' AND '2040-00-00' 
   GROUP BY 
          DATE_FORMAT(Sales.SaleDate, "%Y-%m"),
          Sales.SaleID
  ),
    cte2 AS
  (SELECT *, 
          LAG(`Total_Sales`) OVER (PARTITION BY `SaleID` 
                                   ORDER BY `Month`) AS `Lag_Total_Sales`
   FROM cte1) 

SELECT `Month`, `SaleID`, `Total_Sales`,
       CONCAT(
              ROUND(
                    (`Total_Sales` - `Lag_Total_Sales`) / `Lag_Total_Sales` 
                    , 2) * 100
             , '%') AS `Growth`
FROM cte2

Rextester Demo (MySQL 5.7版本)