table values as table header - sql-server

The query:
select Escuser,Eslevel from WF_UserConfiguration
is returning me the table bellow:
╔═════════════════════╗
║ Escuser Eslevel ║
╠═════════════════════╣
║ A000 1 ║
║ A010 4 ║
║ A021 3 ║
║ ABCD 1 ║
║ C067 3 ║
║ C099 1 ║
║ C252 2 ║
╚═════════════════════╝
My problem is I want to get the following output
╔═════════════════════════════╗
║ 1 2 3 4 ║
╠═════════════════════════════╣
║ A000 C252 A021 A010 ║
║ ABCD C067 ║
║ C099 ║
╚═════════════════════════════╝
The table headers 1, 2, 3 and 4 are EsLevel values of first query result.
How should I get the following result (I mean what query)?

The answer using pivot:
See live demo
select
[1],
[2],
[3],
[4]
from
(
select
Escuser,
Eslevel,
Row_number() over(partition by Eslevel order by escuser asc) as r
from WF_UserConfiguration
)src
pivot
(
max(escuser)
for Eslevel in
(
[1],[2],[3],[4]
)
)p

Related

T-SQL: I'm trying to get the latest row of a column but also the sum of another column

I have the following table, it displays the SalesQty and the StockQty grouped by Article, Supplier, Branch and Month.
╔════════╦════════╦══════════╦═════════╦══════════╦══════════╗
║ Month ║ Branch ║ Supplier ║ Article ║ SalesQty ║ StockQty ║
╠════════╬════════╬══════════╬═════════╬══════════╬══════════╣
║ 201811 ║ 333 ║ 2 ║ 3122 ║ 4 ║ 11 ║
║ 201811 ║ 345 ║ 1 ║ 1234 ║ 2 ║ 10 ║
║ 201811 ║ 345 ║ 1 ║ 4321 ║ 3 ║ 11 ║
║ 201812 ║ 333 ║ 2 ║ 3122 ║ 2 ║ 4 ║
║ 201812 ║ 345 ║ 1 ║ 1234 ║ 3 ║ 12 ║
║ 201812 ║ 345 ║ 1 ║ 4321 ║ 4 ║ 5 ║
║ 201901 ║ 333 ║ 2 ║ 3122 ║ 1 ║ 8 ║
║ 201901 ║ 345 ║ 1 ║ 1234 ║ 6 ║ 9 ║
║ 201901 ║ 345 ║ 1 ║ 4321 ║ 2 ║ 8 ║
║ 201902 ║ 333 ║ 2 ║ 3122 ║ 7 ║ NULL ║
║ 201902 ║ 345 ║ 1 ║ 1234 ║ 4 ║ 13 ║
║ 201902 ║ 345 ║ 1 ║ 4321 ║ 1 ║ 10 ║
╚════════╩════════╩══════════╩═════════╩══════════╩══════════╝
Now I want to sum the SalesQty and get the latest StockQty and group them by Article, Supplier, Branch.
The final result should look like this:
╔════════╦══════════╦═════════╦═════════════╦════════════════╗
║ Branch ║ Supplier ║ Article ║ SumSalesQty ║ LatestStockQty ║
╠════════╬══════════╬═════════╬═════════════╬════════════════╣
║ 333 ║ 2 ║ 3122 ║ 14 ║ NULL ║
║ 345 ║ 1 ║ 1234 ║ 15 ║ 13 ║
║ 345 ║ 1 ║ 4321 ║ 10 ║ 10 ║
╚════════╩══════════╩═════════╩═════════════╩════════════════╝
I already tried this but it gives me an error, and i have no idea what i have to do in this case.
I've made this example so you can try it by yourself. db<>fiddle
SELECT
Branch,
Supplier,
Article,
SumSalesQty = SUM(SalesQty),
-- my attempt
LatestStockQty = (SELECT StockQty FROM TestTable i
WHERE MAX(Month) = Month
AND TT.Branch = i. Branch
AND TT.Supplier = i.Branch
AND TT.Article = i.Branch)
FROM
TestTable TT
GROUP BY
Branch, Supplier, Article
Thank you for your help!
We can try using ROW_NUMBER here, to isolate the latest record for each group:
WITH cte AS (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY Branch, Supplier, Article
ORDER BY Month DESC) rn,
SUM(SalesQty) OVER (PARTITION BY Branch, Supplier, Article) SumSalesQty
FROM TestTable t
)
SELECT
Month,
Branch,
Supplier,
Article,
SumSalesQty,
StockQty
FROM cte
WHERE rn = 1;
Inside the CTE we compute, for each Branch/Supplier/Article group a row number value, starting with 1 for the most recent month. We also compute the sum of the sales quantity over the same partition. Then, we only need to select all rows from that CTE where the row number is equal to 1.
Demo
A similar approach but without the CTE
SELECT top 1 with ties
Branch
, Supplier
, Article
, SUM(SalesQty) OVER (PARTITION BY Branch, Supplier, Article) SumSalesQty
, tt.StockQty as LatestStockQty
FROM TestTable TT
order by ROW_NUMBER() OVER (PARTITION BY Branch, Supplier, Article ORDER BY Month DESC)

Group by Clause in two table - SQL Server

I have two tables with name of WH_table and Store_table,I am trying to create query to get result as mentioned below result table ,Can you anyone help to create query
Warehouse table
╔══════════════╦═════╗
║ Item ║ Qty ║
╠══════════════╬═════╣
║ Foot-ball ║ 1 ║
║ Foot-ball ║ 1 ║
║ Gloves ║ 1 ║
║ Track suites ║ 1 ║
╚══════════════╩═════╝
Store table
╔═══════════╦═════╗
║ Item ║ Qty ║
╠═══════════╬═════╣
║ Foot-ball ║ 1 ║
║ Foot-ball ║ 1 ║
║ Gloves ║ 1 ║
╚═══════════╩═════╝
Result
╔════════════╦═══════════╦══════════════╗
║ Item ║ Qty in WH ║ Qty in Store ║
╠════════════╬═══════════╬══════════════╣
║ Foot-ball ║ 2 ║ 2 ║
║ Gloves ║ 1 ║ 1 ║
║ Tracksuite ║ 1 ║ 0 ║
╚════════════╩═══════════╩══════════════╝
You can use a FULL JOIN:
SELECT ISNULL(w.Item,s.Item) Item,
ISNULL(w.Qty,0) Qty_In_WH,
ISNULL(s.Qty,0) Qty_In_Store
FROM ( SELECT Item,
SUM(Qty) Qty
FROM dbo.Warehouse
GROUP BY Item) w
FULL JOIN ( SELECT Item,
SUM(Qty) Qty
FROM dbo.Store
GROUP BY Item) s
ON w.Item = s.Item;

sp_executesql causing incorrect syntax error in SQL Server 2008 R2 when parameterized

I have this table:
╔═════╦════════╦════════════════╦══════════════════╗
║ drn ║ RecNum ║ Name ║ Value ║
╠═════╬════════╬════════════════╬══════════════════╣
║ 1 ║ 1 ║ ad1_pk ║ 1 ║
║ 2 ║ 1 ║ ad1_address1 ║ P.O. Box 5036 ║
║ 3 ║ 1 ║ ad1_address2 ║ NULL ║
║ 4 ║ 1 ║ ad1_address3 ║ NULL ║
║ 5 ║ 1 ║ ad1_ctyfk ║ 56 ║
║ 6 ║ 1 ║ ad1_postalcode ║ 80155-5036 ║
║ 7 ║ 1 ║ ad1_active ║ Y ║
║ 8 ║ 1 ║ ad1_irstat ║ A ║
║ 9 ║ 1 ║ ad1_irdata ║ NULL ║
║ 10 ║ 1 ║ ad1_at1fk ║ 1 ║
║ 1 ║ 2 ║ ad1_pk ║ 2 ║
║ 2 ║ 2 ║ ad1_address1 ║ 1871 S. Broadway ║
║ 3 ║ 2 ║ ad1_address2 ║ NULL ║
║ 4 ║ 2 ║ ad1_address3 ║ NULL ║
║ 5 ║ 2 ║ ad1_ctyfk ║ 1 ║
║ 6 ║ 2 ║ ad1_postalcode ║ 80210 ║
║ 7 ║ 2 ║ ad1_active ║ Y ║
║ 8 ║ 2 ║ ad1_irstat ║ A ║
║ 9 ║ 2 ║ ad1_irdata ║ NULL ║
║ 10 ║ 2 ║ ad1_at1fk ║ 1 ║
╚═════╩════════╩════════════════╩══════════════════╝
I am creating the pivot using this query:
declare #var nvarchar(max)
declare #sql nvarchar(max)
set #var = STUFF((select ',' + name from (select name from temp where recnum = 1)
as abc for xml path('')),1,1,'')
set #sql = 'select * from temp
pivot(max(value) for name in (' + #var + ')) as pvt'
exec sp_executesql #sql
This query works fine. I just read on google about SQL injection and came to know that my above query if added in stored procedure will have a SQL injection vulnerability.
So I modified the query to this SQL but I am getting error:
"Incorrect syntax near '#var".
declare #var nvarchar(max)
declare #sql nvarchar(max)
set #var = STUFF((select ',' + name from (select name from temp where recnum = 1)
as abc for xml path('')),1,1,'')
set #sql = 'select * from temp
pivot(max(value) for name in ( #var )) as pvt'
exec sp_executesql #sql,N'#var nvarchar(max)',#var
Can someone tell me what is wrong in my second query in which I tried to parameterize it?
I think the issue is, your column list in the outer SELECT statement needs to match the values in the IN statement, which it does not. You have select *, which is incorrect (echoing what #Bacon said). Without knowing exactly what you want, this is how your TSQL should look work:
select [1] as col1, [2] as col2, [3] as col3
from (
select Name, [Value]
from temp) p
pivot(
max([Value]) for Name in ( [1], [2], [3] )
) as pvt
;
You can read more about PIVOT here.

Microsoft sql select distinct certain columns

I am changing mysql queries to microsoft sql server 2008 queries, and in order to apply limit I need to select a ROW_NUMBER() that accumlates over each row and then apply a where condition WHERE RowNum >= 0 AND RowNum < 0 + 20 to select a certain limit with offset.
My issue however is that I can no longer select distinct because I have a column RowNum that is different with each row, here's my query:
USE mydatabase
GO
WITH Results_CTE
AS (
SELECT DISTINCT C.firstname
,C.lastname
,C.id AS clientid
,QC.category_name
,QR.id
,QR.cid
,QR.catid
,QR.rhid
,ROW_NUMBER() OVER (
ORDER BY QR.id DESC
) AS RowNum
FROM cms_question_report QR
,cms_clients C
,cms_questioncategory QC
WHERE C.id = QR.cid
AND QR.catid = '3'
AND QR.catid = QC.id
)
SELECT *
FROM Results_CTE
WHERE RowNum >= 0
AND RowNum < 0 + 20
And the results are:
╔═══════════╦══════════╦══════════╦═══════════════╦═══════╦═════╦═══════╦══════╦════════╗
║ firstname ║ lastname ║ clientid ║ category_name ║ id ║ cid ║ catid ║ rhid ║ RowNum ║
╠═══════════╬══════════╬══════════╬═══════════════╬═══════╬═════╬═══════╬══════╬════════╣
║ test ║ testing ║ 121 ║ Activity Log ║ 81499 ║ 121 ║ 3 ║ 0 ║ 19 ║
║ test ║ testing ║ 121 ║ Activity Log ║ 81498 ║ 121 ║ 3 ║ 0 ║ 20 ║
║ test ║ testing ║ 121 ║ Activity Log ║ 81497 ║ 121 ║ 3 ║ 0 ║ 21 ║
║ test ║ test ║ 120 ║ Activity Log ║ 81496 ║ 120 ║ 3 ║ 0 ║ 22 ║
║ test ║ test ║ 120 ║ Activity Log ║ 81495 ║ 120 ║ 3 ║ 0 ║ 23 ║
║ test ║ test ║ 120 ║ Activity Log ║ 81494 ║ 120 ║ 3 ║ 0 ║ 24 ║
║ test ║ test ║ 120 ║ Activity Log ║ 81493 ║ 120 ║ 3 ║ 0 ║ 25 ║
╚═══════════╩══════════╩══════════╩═══════════════╩═══════╩═════╩═══════╩══════╩════════╝
I took an example from the middle of the result. What I'm after is for example:
╔═══════════╦══════════╦══════════╦═══════════════╦═══════╦═════╦═══════╦══════╦════════╗
║ firstname ║ lastname ║ clientid ║ category_name ║ id ║ cid ║ catid ║ rhid ║ RowNum ║
╠═══════════╬══════════╬══════════╬═══════════════╬═══════╬═════╬═══════╬══════╬════════╣
║ test ║ testing ║ 121 ║ Activity Log ║ 81497 ║ 121 ║ 3 ║ 0 ║ 21 ║
║ test ║ test ║ 120 ║ Activity Log ║ 81496 ║ 120 ║ 3 ║ 0 ║ 22 ║
╚═══════════╩══════════╩══════════╩═══════════════╩═══════╩═════╩═══════╩══════╩════════╝
Where I am trying to group the results by clientid. How do I achieve that?
USE ctarspla_mercycs
GO
WITH Results_CTE AS
(SELECT *, ROW_NUMBER() OVER (ORDER BY CLIENTID DESC) AS RowNum
FROM (SELECT DISTINCT
C.firstname,
C.lastname,
C.id as clientid,
QC.category_name,
QR.catid,
QR.rhid
FROM
cms_question_report QR,
cms_clients C,
cms_questioncategory QC
WHERE C.id=QR.cid
AND QR.catid=3
AND QR.catid=QC.id) t1)
SELECT * FROM Results_CTE
WHERE RowNum >= 0
AND RowNum < 0 + 20

Non-Aggregate Pivot [duplicate]

This question already has an answer here:
SQL transpose full table
(1 answer)
Closed 8 years ago.
I have a table like this:
╔════════╦═══╦═══╦═══╦═══╦═══╗
║ row_id ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║
╠════════╬═══╬═══╬═══╬═══╬═══╣
║ 1 ║ T ║ E ║ S ║ N ║ U ║
║ 2 ║ M ║ B ║ R ║ H ║ A ║
║ 3 ║ C ║ D ║ F ║ G ║ I ║
║ 4 ║ J ║ K ║ L ║ O ║ P ║
║ 5 ║ V ║ W ║ X ║ Y ║ Z ║
╚════════╩═══╩═══╩═══╩═══╩═══╝
I want to "pivot" the table to get an outcome where the row_id column is the first row, the 1 column the second etc.
The results should look like this:
╔════════╦═══╦═══╦═══╦═══╦═══╗
║ row_id ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║
╠════════╬═══╬═══╬═══╬═══╬═══╣
║ 1 ║ T ║ M ║ C ║ J ║ V ║
║ 2 ║ E ║ B ║ D ║ K ║ W ║
║ 3 ║ S ║ R ║ F ║ L ║ X ║
║ 4 ║ N ║ H ║ G ║ O ║ Y ║
║ 5 ║ U ║ A ║ I ║ P ║ Z ║
╚════════╩═══╩═══╩═══╩═══╩═══╝
I've looked for ideas about Pivoting without aggregates but without much luck, mainly since the data I want to pivot is non numeric.
I've set up the sample data in SQL Fiddle.
Thanks!
What you need is called "matrix transposition". The optimal SQL query will depend very much on the actual way you store the data, so it wouldn't hurt if you will provide more realistic example of your table' structure. Are you sure all matrices you will ever need to work with will be exactly 5*5 ? :)
UPD: Oh, I see you've found it.
I realized my mistake was looking for pivot and not for transpose.
I found an answer here and solved the problem with the following query:
SELECT *
FROM (SELECT row_id,
col,
value
FROM table1
UNPIVOT ( value
FOR col IN ([1],
[2],
[3],
[4],
[5]) ) unpiv) src
PIVOT ( Max(value)
FOR row_id IN ([1],
[2],
[3],
[4],
[5]) ) piv
The results are on SQL Fiddle.

Resources