使用日期和总和来调整mysql结果

时间:2016-05-05 07:45:55

标签: php mysql arrays

我在mysql中有一些数据需要我创建一些报告。 我的数据来自以下查询:

SELECT StoreNbr,StoreName,Date, SUM(`Sales`) FROM sales_tbl GROUP BY StoreNbr,StoreName,Date;

这导致以下数据(我的示例只是一小部分):

+-----------+---------------------------+----------------------------+
| StoreNbr | StoreName              | Date       | SUM(Sales)        |
+-----------+---------------------------+----------------------------+
|      1112 | Store1                | 2016-01-16 |            115.09 |
|      1112 | Store1                | 2016-01-17 |             81.00 |
|      1113 | Store2                | 2016-01-16 |            112.44 |
|      1113 | Store2                | 2016-01-17 |             56.61 |

我想将数据转换为这样:

+-----------+---------------------------+----------------------------+
| StoreNbr | StoreName              | 2016-01-16       | 2016-01-17  |
+-----------+---------------------------+----------------------------+
|      1112 | Store1                | 115.09           |       81.00 |
|      1113 | Store2                | 112.44           |       56.61 |

显然,在查询中可能会返回数千行(存储)和未知数量的日期,因为我的查询可能会像这样运行(这需要为日期返回120+列数):

SELECT StoreNbr,StoreName,Date, SUM(`Sales`) FROM sales_tbl WHERE (Date BETWEEN '2016-01-10' AND '2016-05-10') GROUP BY StoreNbr,StoreName,Date;

有几种方法可以做到这一点,没有一个非常简单。我做了一些研究,有些人提到mysql不支持旋转。我正在运行mariadb,并看到mariadb支持通过连接引擎进行透视。我无法使其工作(调整他们的数据上的官方示例)。 另一种方式是大量的IF和案例,但我发现的大多数答案都很难适应,或者只针对要求提供的数据量身定制。 另一种方法是处理数据,因为它们在我的数组中出现,因为我最后有一个json响应,它提供数据表。 - 这是我还没想到的另一种想法。

我正在寻找一种方法来获得所需的输出独立于日期的数量(我猜日期可以被周或其他任何东西取代)。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

选择所有不同的日期

SELECT DISTINCT Date 
FROM sales_tbl 
WHERE (Date BETWEEN '2016-01-10' AND '2016-05-10')
ORDER BY Date;

并初始化一个数组,该数组由存储零的日期索引:

$dateIndexedArray = array();
while($row = $stmt1->fetch(PDO::FETCH_ASSOC) {
    $dateIndexedArray[$row['Date']] = 0;
}

arry看起来像

[
    '2016-01-16' => 0,
    '2016-01-17' => 0
]

然后执行您的查询

SELECT StoreNbr, StoreName,Date, SUM(`Sales`) AS Sales 
FROM sales_tbl
WHERE (Date BETWEEN '2016-01-10' AND '2016-05-10')
GROUP BY StoreNbr,StoreName,Date;

并存储"销售"在每个商店的日期索引数组

$report = array();
while($row = $stmt2->fetch(PDO::FETCH_ASSOC)){
    $storeIndex = $row['StoreNbr'] . ':' . $row['StoreName'];
    if (!isset($report[$storeIndex])) {
        $report[$storeIndex] = array(
            'StoreNbr'  => $row['StoreNbr'],
            'StoreName' => $row['StoreName'],
            'Sales' => $dateIndexedArray
        );
    }
    $report[$storeIndex]['Sales'][$row['Date']] = $row['Sales'];
}

$report数组如下所示:

[
    '1112:Store1' => [
        'StoreNbr'  => 1112,
        'StoreName' => 'Store1',
        'Sales' => [
            '2016-01-16' => 115.09,
            '2016-01-17' => 81.00
        ]
    ],
    '1113:Store2' => [
        'StoreNbr'  => 1113,
        'StoreName' => 'Store2',
        'Sales' => [
            '2016-01-16' => 112.44,
            '2016-01-17' => 56.61
        ]
    ]
]

<强>更新 如果您需要为每个商店将所有数据放在一行中,您可以将代码更改为:

$report = array();
while($row = $stmt2->fetch(PDO::FETCH_ASSOC)){
    $storeIndex = $row['StoreNbr'] . ':' . $row['StoreName'];
    if (!isset($report[$storeIndex])) {
        $report[$storeIndex] = $dateIndexedArray;
        $report[$storeIndex]['StoreNbr']  = $row['StoreNbr'];
        $report[$storeIndex]['StoreName'] = $row['StoreName'];
    }
    $report[$storeIndex][$row['Date']] = $row['Sales'];
}

生成的数组如下所示:

[
    '1112:Store1' => [
        'StoreNbr'  => 1112,
        'StoreName' => 'Store1'
        '2016-01-16' => 115.09,
        '2016-01-17' => 81.
    ],
    '1113:Store2' => [
        'StoreNbr'  => 1113,
        'StoreName' => 'Store2',
        '2016-01-16' => 112.44,
        '2016-01-17' => 56.61
    ]
]

更新2 :要获得每个商店的总销售额,您可以使用WITH ROLLUP

SELECT StoreNbr, StoreName,Date, SUM(`Sales`) AS Sales 
FROM sales_tbl
WHERE (Date BETWEEN '2016-01-10' AND '2016-05-10')
GROUP BY StoreNbr,StoreName,Date WITH ROLLUP;
$report = array();
while($row = $stmt2->fetch(PDO::FETCH_ASSOC)){
    if ($row['StoreName'] === null) {
        // Skip this row.
        // It contains total sales grouped by StoreNbr 
        // (or not grouped if StoreNbr === null).
        continue;
    }
    $storeIndex = $row['StoreNbr'] . ':' . $row['StoreName'];
    if (!isset($report[$storeIndex])) {
        $report[$storeIndex] = $dateIndexedArray;
        $report[$storeIndex]['StoreNbr']  = $row['StoreNbr'];
        $report[$storeIndex]['StoreName'] = $row['StoreName'];
    }
    if ($row['Date'] === null) {
        // This row contains total sales grouped by StoreNbr & StoreName
        $report[$storeIndex]['TotalSales'] = $row['Sales']
    } else {
        $report[$storeIndex][$row['Date']] = $row['Sales'];
    }
}

请注意,我从未使用WITH ROLLUP。所以你可能需要调整代码。