Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Group Count of Item ordered with dynamic numbers of Columns

SQL Server 2012. I wonder if anyone can figure out this problem I have.

I want to find all the different combinations people have ordered articles. I'm not interested if the person have bought a A and B and an other ordered B and then A. I want the count of columns to be dynamic. Max count of rows that a order have.

Example of Orders

Order   Row Art
1       1   A
1       2   B
1       3   C
2       1   A
2       2   B
3       1   C
3       2   D
4       1   A
4       2   B
5       1   B
5       2   A

And the result I want is like this

Count   Art1    Art2    Art3
3       A       B   
1       C       D   
1       A       B       C
like image 576
Jonas Avatar asked Mar 09 '23 14:03

Jonas


2 Answers

Here's an approach:

  • First get all products in a column (in ordered fashion)
  • Second group them by this column to get count
  • separate out as columns

Below is the query

--Create table t1 ([order] int, row int, art varchar(30))

--insert into t1 values 
--(1,1,'A'),
--(1,2,'B'),
--(1,3,'C'),
--(2,1,'A'),
--(2,2,'B'),
--(3,1,'C'),
--(3,2,'D'),
--(4,1,'A'),
--(4,2,'B'),
--(5,1,'B'),
--(5,2,'A')

    select 
        count(1) as [count], 
        articles,
        max(numberOfArticles) as numberOfArticles
    from 
    (
        select 
        [order],
        count(1) as numberOfArticles,
        Stuff(          
                (
                SELECT 
                    ',' + art 
                FROM t1 AS i
                WHERE i.[order]=o.[order]
                ORDER by art asc
                FOR XML PATH ('')
                ), 
            1, 1, '') as articles
        from t1 o
        group by [order]
    )t
    group by articles

--drop table t1

Output: enter image description here

like image 110
DhruvJoshi Avatar answered Mar 12 '23 02:03

DhruvJoshi


You can use PIVOT first to create a pivoted version of your table, then apply GROUP BY in order to get the count of all possible combinations:

SELECT COUNT(*), Art1, Art2, Art3
FROM (
   SELECT [Order], [1] AS Art1, [2] AS Art2, [3] AS Art3
   FROM 
   (
      SELECT [Order], Art, 
             ROW_NUMBER() OVER (PARTITION BY [Order] 
                                ORDER BY Art) AS [Row]
      FROM mytable
   ) AS src
   PIVOT 
   (
      MAX(Art) FOR [Row] IN ([1], [2], [3])
   ) AS pvt    
) AS t
GROUP BY Art1, Art2, Art3

Note the usage of ROW_NUMBER: it re-creates Row field so that Art values are always ordered the same way within each Order partition.

Demo here

like image 33
Giorgos Betsos Avatar answered Mar 12 '23 02:03

Giorgos Betsos