SQL to list data in tabular structure - sql

MSSQL Table1 has following data:
AttributeID | ProductID | Attribute | Value |
--------------------------------------------------
1 | 1111 | Attribute1 | Prod1_Val1 |
2 | 1111 | Attribute2 | Prod1_Val2 |
3 | 1111 | Attribute3 | Prod1_Val3 |
4 | 2222 | Attribute1 | Prod2_Val1 |
5 | 2222 | Attribute2 | Prod2_Val2 |
6 | 2222 | Attribute3 | Prod2_Val3 |
7 | 3333 | Attribute1 | Prod3_Val1 |
8 | 3333 | Attribute2 | Prod3_Val2 |
9 | 3333 | Attribute3 | Prod3_Val3 |
10 | 4444 | Attribute1 | Prod4_Val1 |
11 | 4444 | Attribute2 | Prod4_Val2 |
12 | 5555 | Attribute4 | Prod5_Val1 |
MSSQL Table2 has following Data:
ProductID | ProductName |
--------------------------------------------------
1111 | Product1 |
2222 | Product2 |
3333 | Product3 |
4444 | Product4 |
5555 | Product5 |
The result I would require is:
Product | Product1 | Product3 | Product3 | Product4 | Product5 |
Attribute1 | Prod1_Val1 | Prod2_Val1 | Prod3_Val1 | Prod4_Val1 | -- |
Attribute2 | Prod1_Val2 | Prod2_Val2 | Prod3_Val2 | Prod4_Val2 | -- |
Attribute3 | Prod1_Val3 | Prod2_Val3 | Prod3_Val3 | -- | -- |
Attribute4 | -- | -- | -- | -- | Prod5_Val1 |
Attribute5 | -- | -- | -- | -- | -- |
I would like to know whether this desired result can be achieved with SQL itself using Table1 and Table2. If yes, please assist me by providing the SQL. Thanks for your timely assistance in advance.

As alluded to by TomTom, you will need to use the SQL Server's PIVOT operator:
SELECT Attribute, [Product1], [Product2], [Product3], [Product4], [Product5]
FROM (
SELECT ProductName, Attribute, Value
FROM Table1
INNER JOIN Table2 ON ( Table2.ProductId = Table1.ProductId )
) AS SourceTable
PIVOT (
Min(Value)
FOR ProductName IN ([Product1], [Product2], [Product3], [Product4], [Product5])
) AS PivotTable
Be aware that you will need to decide up front how many columns (that is, [Product1], [Product2], ..., [ProductN]) you would like to output when writing your SQL query.
Also, since PIVOT aggregates data, the example above uses the Min() function. (You could just as easily use Max(), or a different aggregation function, based upon your needs.) Your output will be NULL for all elements that do not have values.

Related

SQL - Custom Select View after Joining Multiple Tables

Very simple question and I just can't seem to figure it out.
I have the two tables below. I would like to write a select query that returns the following
| UID | NAME | DESCRIPTION | CC_CONFIG_UID |
├------+---------+-------------+---------------┤
| xxx | HELLO_1 | NULL | abc |
| yyy | WORLD_1 | NULL | hij |
| aaa | NULL | HELLO_2 | efg |
| bbb | NULL | WORLD_2 | klm |
Table A:
| UID | NAME | CC_CONFIG_UID |
|------+---------+---------------|
| xxx | HELLO_1 | abc |
| yyy | WORLD_1 | hij |
Table B:
| UID | DESCRIPTION | CC_CONFIG_UID |
|------+-------------+---------------|
| aaa | HELLO_2 | efg |
| bbb | WORLD_2 | klm |
I have tried
(SELECT * FROM A) UNION (SELECT * FROM B)
But I get the following in return, which is close but not what I need:
| UID | NAME | CC_CONFIG_UID |
├------+---------+---------------┤
| xxx |HELLO_1 | abc |
| aaa |HELLO_2 | def |
| yyy |WORLD_1 | hig |
| bbb |WORLD_2 | klm |
You need to specify the columns. Your tables have three columns, but you want the result set to have four:
select a.uid, a.name, null as description, a.cc_config_uid
from a
union all
select b.uid, null as name, bdescription, b.cc_config_uid
from b;

Having Groups based on distinct count of another column

I have a table as follow :
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Design | XYZ |
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
+-------------+-----------+------+
I want to output only the groups that have unique teams greater than 3.
Only group 2 has this condition so the output is :
Expected Output:
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
+-------------+-----------+------+
not sure how to utilize this in subquery
SELECT count(Distinct(TeamName))
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
Simply put it in a Subquery:
select *
from mytable
where [GroupNumber] in
(
SELECT [GroupNumber]
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
)
Please try
SELECT *
FROM mytable where GroupNumber in (select GroupNumber
FROM mytable group by TeamName
HAVING COUNT(TeamName)>3)

Turn columns into separate table with column name as values

I'm working on an extraction and I have an issue I can't quite solve.
My extraction looks like this :
+--------+-------+----------+----------+-----+------------+
| ID | Info1 | Product1 | Product2 | ... | Product300 |
+--------+-------+----------+----------+-----+------------+
| 1 | Paul | 2 | | | |
+--------+-------+----------+----------+-----+------------+
| 2 | Steve | | 1 | | |
+--------+-------+----------+----------+-----+------------+
| 3 | Mark | 2 | | | |
+--------+-------+----------+----------+-----+------------+
| ... | | | | | |
+--------+-------+----------+----------+-----+------------+
| 150000 | Felix | 1 | | | 2 |
+--------+-------+----------+----------+-----+------------+
Products appear as columns. So it's not very easy to use.
I want to split my table with product as an external table like :
+--------+----------+-------+
| ID | Product | Value |
+--------+----------+-------+
| 1 | Product1 | 2 |
+--------+----------+-------+
| 2 | Product2 | 1 |
+--------+----------+-------+
| ... | | |
+--------+----------+-------+
| 150000 | Product1 | 1 |
+--------+----------+-------+
Initially this extraction is in Excel but I moved to Access for this purpose.
I have basic knowledge of SQL but not enough to figure out a solution.
As jarlh wrote, the only SQL solution is this:
INSERT INTO TargetTable (ID, Product, Value)
SELECT ID, 'Product1' AS Product, Product1 AS Value FROM SrcTable WHERE Product1 IS NOT NULL
UNION ALL
SELECT ID, 'Product2' AS Product, Product2 AS Value FROM SrcTable WHERE Product2 IS NOT NULL
UNION ALL
etc.
Maybe split it up into chunks, I'm not sure how well 300 UNION ALLs will work in one query.
You need to unpivot your table:
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
SELECT ID, Product, Value
FROM
(SELECT ID, Product1, Product2, Product3, Product4, Product5
FROM products) p
UNPIVOT
(Value FOR Product IN
(Product1, Product2, Product3, Product4, Product5)
)AS unpvt;

Kindly advice on how to group the data in SQL

Example table
Cust_no | Item_no | Discount_Amt |Discount_%|
A123 | ITEM123 | 0.1 | |
AB321 | ITEM123 | 50 | |
A123 | ITEM123 | | 3 |
CD343 | ITEM345 | | 2 |
and the result I want:
Cust_no | Item_no | Discount Amt| Discount_%|
A123 | ITEM123 | 0.1 | 3 |
AB321 | ITEM123 | 50 | 0 |
CD343 | ITEM345 | | 2 |
How can I get that result in SQL?
Try this :
SELECT Cust_no,Item_no,SUM(Discount_Amt),SUM(Discount_%)
FROM TableName
GROUP BY Cust_no,Item_no
I think you are looking something similar to this
SELECT Cust_no,Item_no, MAX(Discount_Amt),MAX(Discount_%)
FROM Table
GROUP BY Cust_no, Item_no

Concat multiple rows with dynamic table in SQL Server [duplicate]

This question already has answers here:
How to use GROUP BY to concatenate strings in SQL Server?
(22 answers)
Closed 6 years ago.
I have two tables where I joined both to get the first view, after that I'd like to do GROUP_CONCAT in one column, but we don't have this function in SQL Server.
So I tried some examples here, but was unsuccessful with my SQL. Examples found always use a table to generate GROUP_CONCAT, but I didn't find any example with a SQL result.
TableA:
| CityID | MasterID | Account |
+-----------------------------+
| 01 | 1234 | 1111 |
| 01 | 1234 | 2222 |
| 01 | 1234 | 3333 |
| 02 | 1234 | 4444 |
TableB:
| Account | Item | Price |
+------------------------+
| 1111 | A001 | 11,11 |
| 2222 | A001 | 11,11 |
| 3333 | A002 | 22,22 |
| 4444 | A002 | 22,22 |
| 5555 | A002 | 22,22 |
First SQL - Subselect:
SELECT *
FROM TableA, TableB
WHERE TableA.AccountID = TableB.AccountID
Output:
| CityID | MasterID | Account | Account | Item | Price |
+------------------------------------------------------+
| 01 | 1234 | 1111 | 1111 | A0001 | 11,11 |
| 01 | 1234 | 2222 | 2222 | A0001 | 11,11 |
| 01 | 1234 | 3333 | 3333 | A0002 | 22,22 |
| 02 | 1234 | 4444 | 4444 | A0002 | 22,22 |
Second SQL - final view:
SELECT
MasterID, GROUP_CONCAT(Item)
FROM
(SELECT *
FROM TableA, TableB
WHERE TableA.AccountID = TableB.AccountID) table01
Output:
| MasterID | Item |
+-----------------+
| 1234 | A0001,A002 |
This will give you expected result (I'm using Account as column name rather than AccountId as that's what you mentioned in table structure)
;WITH table01
AS
(
SELECT A.CityId,A.MasterId,A.Account Account1,B.Account Account2,B.Item,B.Price
FROM TableA A
INNER JOIN TableB B
ON A.Account = B.Account
)
SELECT A.MasterId,
STUFF(( SELECT ', ' + B.ITEM
FROM table01 B
WHERE B.MasterId = A.MasterId
group by B.MasterId,B.Item
FOR XML PATH('')
), 1, 2, '') Item
FROM table01 A
GROUP BY A.MasterId