简体   繁体   中英

Issue with SQL Group By and COALESCE on sqlite

I have a table as below in sqlite database. I want to create a line chart showing usage by product groups.

Table: ProductUsageData

UserID  ProductName ProductGroup    Qty RecordID
1       A1          A               12  1   
2       A1          A               12  1   
1       A2          A               15  1   
3       A1          A               12  2   
2       B1          B               12  2   
5       B2          B               5   2
1       A1          A               12  3   
1       A2          A               15  3   
4       A1          A               12  3   
3       C1          C               12  3   
2       C2          C               15  3

Since I want separate line for each ProductGroup I am using below Query

SELECT 
      SUM(Qty) as UsedQty, 
      ProductGroup, 
      RecordID 
FROM ProductUsageData 
GROUP BY ProductGroup, RecordID  
ORDER BY RecordID ASC;

While I get three records for A (for each RecordID) I get only 1 record each for B & C as they are not used during each RecordID. Problem is when I am putting one line for each ProductGroup in the chart, the points for B & C are shown as per Qty in the first My output is like this

A   39  1
A   12  2
B   17  2
A   39  3
C   27  3   

So the graph looks like this

在此处输入图片说明

instead of

在此处输入图片说明

To fix this I changed the query using COALESCE to get 0 Qty if the ProductGroup is not used during each recording.

SELECT 
       COALESCE(SUM(Qty), 0) as UsedQty, 
       ProductGroup, 
       RecordID 
FROM ProductUsageData 
GROUP BY ProductGroup, RecordID  
ORDER BY RecordID ASC;

I was expecting output as below

A   39  1
B   0   1
C   0   1
A   12  2
B   17  2
C   0   2
A   39  3
B   0   3
C   27  3

But I am getting same output as first

Please let me know how can I correct the query to get desired output

A typical solution is to first cross join two queries that select the distinct product groups and record ids from the table; this gives you all possible combinations of productGroup and recordID .

Then, you can bring in the original table with a left join , and aggregate:

select
    g.productGroup,
    coalesce(sum(p.qty), 0) qty,
    r.recordID
from (select distinct productGroup from productUsageData) g
cross join (select distinct recordID from productUsageData) r
left join productUsageData p
    on  p.productGroup = g.productGroup
    and p.recordID = r.recordID
group by r.recordID, g.productGroup
order by r.recordID, g.productGroup

In the real world, you might have separate referential tables for product groups and records ids, which would make the query simpler and more efficient (since it would avoid the need to select distinct in subqueries).

Demo on DB Fiddle :

productGroup | qty | recordID
:----------- | :-- | :-------
A            | 39  | 1       
B            | 0   | 1       
C            | 0   | 1       
A            | 12  | 2       
B            | 17  | 2       
C            | 0   | 2       
A            | 39  | 3       
B            | 0   | 3       
C            | 27  | 3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM