SQL to combine data for single row per object - sql-server

I know this must be a common problem, but I'm not sure where to go. This occurs a few times inside a big nasty query, so here is the problem simplified. I just want one row per object, but the null on ColorOther gives me two rows.
I can think of a few things to try wrapping a query around this, but there must be something simpler... I'm off to read up on pivots.
Table structure
CREATE TABLE [dbo].[Colors](
[ColorId] [int] IDENTITY(1,1) NOT NULL,
[ColoredObjectId] [int] NOT NULL,
[ColorCode] [int] NOT NULL,
[ColorOther] [nvarchar](50) NULL,
CONSTRAINT [PK_Colors] PRIMARY KEY CLUSTERED
([ColorId] ASC)
Source data
ColorId ColoredObjectId ColorCode ColorOther
----------- --------------- ----------- ----------
1 1 1 NULL
2 1 2 NULL
3 1 4 purple
4 2 2 NULL
5 2 3 NULL
6 2 4 orange
7 3 1 NULL
8 3 3 NULL
9 3 4 green
Query
SELECT ColoredObjectId ,
ColorOther ,
MAX(CASE WHEN ColorCode = 1 THEN 1 ELSE 0 END) AS Yellow,
MAX(CASE WHEN ColorCode = 2 THEN 1 ELSE 0 END) AS Red ,
MAX(CASE WHEN ColorCode = 3 THEN 1 ELSE 0 END) AS Blue ,
MAX(CASE WHEN ColorCode = 4 THEN 1 ELSE 0 END) AS Other
FROM Colors
GROUP BY ColoredObjectId,
ColorOther
Output
ColoredObjectId ColorOther Yellow Red Blue Other
--------------- ---------- ----------- ----------- ----------- -----------
1 NULL 1 1 0 0
1 purple 0 0 0 1
2 NULL 0 1 1 0
2 orange 0 0 0 1
3 NULL 1 0 1 0
3 green 0 0 0 1
Desired output
ColoredObjectId ColorOther Yellow Red Blue Other
--------------- ---------- ----------- ----------- ----------- -----------
1 purple 1 1 0 1
2 orange 0 1 1 1
3 green 1 0 1 1

I think this should return the desired output.
SELECT ColoredObjectId ,
MAX(ColorOther) AS ColorOther ,
MAX(CASE WHEN ColorCode = 1 THEN 1 ELSE 0 END) AS Yellow,
MAX(CASE WHEN ColorCode = 2 THEN 1 ELSE 0 END) AS Red ,
MAX(CASE WHEN ColorCode = 3 THEN 1 ELSE 0 END) AS Blue ,
MAX(CASE WHEN ColorCode = 4 THEN 1 ELSE 0 END) AS Other
FROM Colors
GROUP BY ColoredObjectId

Try this (I am not at a SQL box, so I can't test it, but it should be pretty close)
SELECT cc.ColoredObjectId ,
xx.ColorOther ,
MAX(CASE WHEN ColorCode = 1 THEN 1 ELSE 0 END) AS Yellow,
MAX(CASE WHEN ColorCode = 2 THEN 1 ELSE 0 END) AS Red ,
MAX(CASE WHEN ColorCode = 3 THEN 1 ELSE 0 END) AS Blue ,
MAX(CASE WHEN ColorCode = 4 THEN 1 ELSE 0 END) AS Other
FROM Colors cc
JOIN (select distinct ColorObjectID,ColorOther FROM colors
where colorOther is not null) xx on xx.colorObjectId=cc.colorobjectID
GROUP BY cc.ColoredObjectId,
xx.ColorOther

Related

Insert Query in SQL Server

I have this table TAB
ID | Trans
------------
1 | 99
2 | 99
3 | 99
2 | 90
4 | 22
4 | 22
2 | 99
2 | 90
I want to get the count of trans that appear together for a single id, for eg, '1 has 90 & 99' and '2 has 90 & 99' in the entire table so the count is 2. This is similar to Apriori Algorithm's Third Step.
I tried this but didn't work-
select
count(trans)
from
Tab
where
trans = 99 & 90
group by
ID
having
ID = 2
My expected ans for Trans- 90 & 99 is
Trans1 | Trans2 | Support
------------
90 | 99 | 1
I also want to insert this into a new table.
If I understood your problem correctly, you can use SUM(CASE WHEN...END) for this:
DECLARE
#trans1 INT = 99,
#trans2 INT = 90
SELECT
ID,
PairCount =
CASE
WHEN SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END) >= SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
THEN SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
ELSE SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END)
END,
Trans1 = SUM(CASE WHEN Trans = #trans1 THEN 1 ELSE 0 END),
Trans2 = SUM(CASE WHEN Trans = #trans2 THEN 1 ELSE 0 END)
FROM DS
WHERE Trans IN (#trans1, #trans2)
GROUP BY ID
RESULT
ID PairCount Trans1 Trans2
----------- ----------- ----------- -----------
1 0 1 0
2 2 2 2
3 0 1 0

Populate Sequence Number by Repeated fields in Coloumns

i have below data in my table
description id
-------------- ------
desc1 0
desc2 0
desc3 0
desc4 1
desc5 1
desc6 1
I need below
description id sequenceNo
-------------- ------ ------------------
desc1 0 1
desc2 0 2
desc3 0 3
desc4 1 1
desc5 1 2
desc6 1 3
Please let me know how to solve this query by using sql function or any other alternative..?
try this
select *,ROW_NUMBER() Over(partition By ID order by ID asc)
as sequenceNo from Mytable

SQL - Group based on multi - columns

I have table like the following :
A_ID Area_Code Status
1 AAA 2
2 BBB 1
3 AAA 2
4 AAA 3
5 AAA 2
6 BBB 2
7 BBB 1
8 AAA 4
9 AAA 5
10 AAA 4
And i want the result set like :
A_Code Count_A_Code Count_Sts1 Count_Sts2 Count_Sts3 Count_Sts4 Count_Sts5
AAA 7 0 3 1 2 1
BBB 3 2 1 0 0 0
Please note that i have only 5 statues . so i need the statues to be columns ..
I appreciate any help . thanks
select area_code as a_code,
count(*) as count_a_code,
sum(case when status = 1 then 1 else 0 end) as code_count_sts1,
sum(case when status = 2 then 1 else 0 end) as code_count_sts2,
sum(case when status = 3 then 1 else 0 end) as code_count_sts3,
sum(case when status = 4 then 1 else 0 end) as code_count_sts4,
sum(case when status = 5 then 1 else 0 end) as code_count_sts5
from your_table
group by area_code

Count and Group By for products sold

I have a table Transaction & a table product as below .
Each Transaction has multiple products.
ProductId Name
1 ABC
2 DEF
3 GHI
Each transaction can have multiple products sold.
TransactionId ProductSoldInDept1 ProductSoldinDept2 ProductSoldinDept3
1 1 null null
2 1 2 null
3 3 1 null
4 2 3 1
I am planning to generate a report and I would like to get a result something like this :
This shows the number of products sold per each department grouped by Id
Expected Result :
ProductID Department1ProdCount Department2ProdCount Department3ProdCount
1 2 1 1
2 1 1 0
3 1 1 0
I could get till here , this is a query to get the counts for one specific product
which is productid : 1
I would like to know how I could use a group by here :
select Count(CASE WHEN ProductSoldInDept1 = 1 THEN 1 END) ,
Count(CASE WHEN ProductSoldInDept2 = 1 THEN 1 END) ,
Count(CASE WHEN ProductSoldInDept3 = 1 THEN 1 END)
from Table1
SELECT
p.ProductID,
Dept1ProdCount = COUNT(CASE WHEN t.ProductSoldInDept1 = p.ProductID THEN 1 END),
Dept2ProdCount = COUNT(CASE WHEN t.ProductSoldInDept2 = p.ProductID THEN 1 END),
Dept3ProdCount = COUNT(CASE WHEN t.ProductSoldInDept3 = p.ProductID THEN 1 END)
FROM dbo.Product AS p
LEFT OUTER JOIN dbo.[Transaction] AS t
ON p.ProductID IN
(t.ProductSoldInDept1, t.ProductSoldinDept2, t.ProductSoldinDept3)
GROUP BY p.ProductID;
Result
| PRODUCTID | DEPT1PRODCOUNT | DEPT2PRODCOUNT | DEPT3PRODCOUNT |
----------------------------------------------------------------
| 1 | 2 | 1 | 1 |
| 2 | 1 | 1 | 0 |
| 3 | 1 | 1 | 0 |
See a demo
Try this
select ProductID,
v.Department1ProdCount, v.Department2ProdCount, v.Department3ProdCount
from product a
cross apply
(
select Count(CASE WHEN ProductSoldInDept1 = a.ProductID THEN 1 END) Department1ProdCount,
Count(CASE WHEN ProductSoldInDept2 = a.ProductID THEN 1 END) Department2ProdCount,
Count(CASE WHEN ProductSoldInDept3 = a.ProductID THEN 1 END) Department3ProdCount
from Table1
) v
This:
TransactionId ProductSoldInDept1 ProductSoldinDept2 ProductSoldinDept3
1 1 null null
2 1 2 null
3 3 1 null
4 2 3 1
might be better structured as this:
transid prodsold deptid
1 1 1
2 1 1
2 2 2
3 3 1
3 1 2
4 2 1
4 3 2
4 1 3
I think that would make your queries easier to write.

Pivot/aggregation with percentage columns possible in t-sql?

Struggling with this a bit in SQL Server, any ideas? Given this data (ID is an INT, the rest are BITs):
------------------------------------------
ID Type1 Type2 AttrA AttrB AttrC
------------------------------------------
1 1 0 1 0 0
2 1 0 1 0 0
3 1 1 0 1 1
4 0 1 1 1 0
5 1 1 1 1 0
I would like to produce this report:
---------------------------------------------------------
Attr NumOfType1 PctOfType1 NumOfType2 PctOfType2
---------------------------------------------------------
AttrA 3 75% 2 67%
AttrB 2 50% 3 100%
AttrC 1 25% 1 33%
Total 4 N/A 3 N/A
Thanks!
Jim
;WITH YourBaseTable AS
(
SELECT 1 ID, 1 Type1,0 Type2, 1 AttrA, 0 AttrB, 0 AttrC UNION ALL
SELECT 2 ID, 1 Type1,0 Type2, 1 AttrA, 0 AttrB, 0 AttrC UNION ALL
SELECT 3,1,1,0,1,1 UNION ALL
SELECT 4,0,1,1,1,0 UNION ALL
SELECT 5,1,1,1,1,0
), T AS
(
SELECT *, 1 AS Total
FROM YourBaseTable
)
SELECT
Attr,
COUNT(CASE WHEN VALUE = 1 AND Type1 = 1 THEN 1 END) NumOfType1,
CASE WHEN Attr <> 'Total' THEN 100 * CAST(COUNT(CASE WHEN VALUE = 1 AND Type1 = 1 THEN 1 END) AS FLOAT)/COUNT(CASE WHEN Type1 = 1 THEN 1 END) END PctOfType1,
COUNT(CASE WHEN VALUE = 1 AND Type2 = 1 THEN 1 END) NumOfType2,
CASE WHEN Attr <> 'Total' THEN 100 * CAST(COUNT(CASE WHEN VALUE = 1 AND Type2 = 1 THEN 1 END) AS FLOAT)/COUNT(CASE WHEN Type2 = 1 THEN 1 END) END PctOfType2
FROM T
UNPIVOT
(VALUE FOR Attr IN (AttrA, AttrB,AttrC, Total)) AS unpvt
GROUP BY Attr

Resources