Postgresql union, чтобы получать продажи за все дни и часы и итоговую строку - PullRequest
0 голосов
/ 16 ноября 2018

У нас есть 2 таблицы и запрос для получения данных о продажах за каждый час и каждый день, а также итоговая строка для каждого дня.

Таблица:

  1. sales_table - данные о продажах
  2. date_hour - перечисляет все даты и их часы (24 часа в сутки)

Запрос:

with b as (
SELECT
    a.purchase_date,
    CAST(DATE_PART("HOUR", CAST(a.purchase_date AS DATETIME)) as INTEGER) AS 
Hour,
    COUNT(a.quantity) AS QtyCount,
    SUM(a.quantity) AS QtyTotal,
    SUM((a.item_price) AS Price
FROM sales_table a
GROUP BY Hour, a.purchase_date
),
a as (
     SELECT
          DATE_FORMAT(DateT, "yyyy-MM-dd") AS datet,
          CAST(hourt AS INTEGER) AS hourt,
          QtyCount,
          QtyTotal,
          Price
     FROM date_hour
), 
c as (
     SELECT
       a.purchase_date,
       CAST(DATE_PART("HOUR", CAST(a.purchase_date AS DATETIME)) as INTEGER)  
 AS Hour,
       COUNT(a.quantity) AS QtyCount,
       SUM(a.quantity) AS QtyTotal,
       SUM((a.item_price) AS Price
FROM sales_table a
GROUP BY a.purchase_date
) --summary row subquery
Select   --summary row
     c.purchase_date,
     "Day Total" AS Hour,
     if(c.QtyCount is null, 0, c.QtyCount) QtyCount,
     if(c.QtyTotal is null, 0, c.QtyTotal) QtyTotal,
     if(c.Price is null, 0, c.Price) AS Price
FROM a LEFT JOIN c
ON a.datet = c.purchase_date
UNION
Select
     a.datet AS Date,
     a.hourt AS Hour,
     if(c.QtyCount is null, 0, c.QtyCount) QtyCount,
     if(c.QtyTotal is null, 0, c.QtyTotal) QtyTotal,
     if(c.Price is null, 0, c.Price) AS Price
FROM a LEFT JOIN b
ON a.datet = b.purchase_date AND a.hourt = b.Hour
ORDER BY Date, c.hour

Пример результата:

<style type="text/css">
	table.tableizer-table {
		font-size: 12px;
		border: 1px solid #CCC; 
		font-family: Arial, Helvetica, sans-serif;
	} 
	.tableizer-table td {
		padding: 4px;
		margin: 3px;
		border: 1px solid #CCC;
	}
	.tableizer-table th {
		background-color: #104E8B; 
		color: #FFF;
		font-weight: bold;
	}
</style>
<table class="tableizer-table">
<thead><tr class="tableizer-firstrow"><th>Date</th><th>Hour</th><th>QtyCount</th><th>QtyTotal</th><th>Price</th></tr></thead><tbody>
 <tr><td>2018-11-02</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>1</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>2</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>3</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>4</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>5</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>6</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>7</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>8</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>9</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>10</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>11</td><td>1</td><td>1</td><td>6.99</td></tr>
 <tr><td>2018-11-02</td><td>12</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>13</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>14</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>15</td><td>1</td><td>1</td><td>69.95</td></tr>
 <tr><td>2018-11-02</td><td>16</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>17</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>18</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>19</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>20</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>21</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>22</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>23</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-02</td><td>&nbsp;</td><td>2</td><td>2</td><td>76.94</td></tr>
 <tr><td>2018-11-03</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>1</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>2</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>3</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>4</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>5</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>6</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>7</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>8</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>9</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>10</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>11</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>12</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>13</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>14</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>15</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>16</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>17</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>18</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>19</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>20</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>21</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>22</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-03</td><td>23</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>1</td><td>1</td><td>3</td><td>209.85</td></tr>
 <tr><td>2018-11-04</td><td>2</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>3</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>4</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>5</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>6</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>7</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>8</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>9</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>10</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>11</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>12</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>13</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>14</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>15</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>16</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>17</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>18</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>19</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>20</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>21</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>22</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>23</td><td>0</td><td>0</td><td>0</td></tr>
 <tr><td>2018-11-04</td><td>&nbsp;</td><td>1</td><td>3</td><td>209.85</td></tr>
</tbody></table>

Запрос работает, но итоговая строка не указана вверху. Можно ли перечислять итоговую строку в верхней части каждого дня (до часа 0 этого дня) и включать итоговую строку, когда продаж не было (11/3 в приведенном выше примере), в виде нулей по горизонтали? Заранее спасибо за помощь.

1 Ответ

0 голосов
/ 16 ноября 2018

Не вдаваясь в подробности, я думаю, что все, что вам нужно, - это столбец, чтобы помочь с заказом

with (....
 ...
)
Select   --summary row
     0 as ordr,
     c.purchase_date,
     "Day Total" AS Hour,
     if(c.QtyCount is null, 0, c.QtyCount) QtyCount,
     if(c.QtyTotal is null, 0, c.QtyTotal) QtyTotal,
     if(c.Price is null, 0, c.Price) AS Price
FROM a LEFT JOIN c
ON a.datet = c.purchase_date
UNION
Select
     1 as ordr,
     a.datet AS Date,
     a.hourt AS Hour,
     if(c.QtyCount is null, 0, c.QtyCount) QtyCount,
     if(c.QtyTotal is null, 0, c.QtyTotal) QtyTotal,
     if(c.Price is null, 0, c.Price) AS Price
FROM a LEFT JOIN b
ON a.datet = b.purchase_date AND a.hourt = b.Hour
ORDER BY Date, ordr, hour

Я предлагаю вам изучить ROLLUP , что может упростить ваш запрос.


Чтобы получить сводку по каждой дате, вам нужно использовать cte «a» в качестве базовой таблицы, слева присоединиться к sales_table, см. «C» ниже. Это непроверенный и только предложение, вам нужно будет сделать любое отладки.

with a as (
     SELECT
          DATE_FORMAT(DateT, "yyyy-MM-dd") AS datet,
          CAST(hourt AS INTEGER) AS hourt,
          QtyCount,
          QtyTotal,
          Price
     FROM date_hour
    )
, b as (
SELECT
    a.purchase_date,
    CAST(DATE_PART("HOUR", CAST(a.purchase_date AS DATETIME)) as INTEGER) AS 
Hour,
    COUNT(a.quantity) AS QtyCount,
    SUM(a.quantity) AS QtyTotal,
    SUM((a.item_price) AS Price
FROM sales_table a
GROUP BY Hour, a.purchase_date
    )
, c as (
     SELECT
       a.datet as purchase_date,
       CAST(DATE_PART("HOUR", CAST(st.purchase_date AS DATETIME)) as INTEGER)   AS Hour,
       COUNT(st.quantity) AS QtyCount,
       SUM(st.quantity) AS QtyTotal,
       SUM((st.item_price) AS Price
FROM a
left join sales_table st ON a.datet = c.purchase_date
GROUP BY a.datet
) --summary row subquery

btw"a" "b" "c" и т. Д. Очень разочаровывающие псевдонимы. Я думаю, что вещи типа "st" (Sales Table) более полезны.

...