Unexpected inner join behavior - sql-server

I've a query :
select TABLE.NAME,
max(case when TABLE_ADDITION.CODE= 1 then TABLE_ADDITION.VALUE end) Mach1,
max(case when TABLE_ADDITION.CODE= 4 then TABLE_ADDITION.VALUE end) Source,
max(case when TABLE_ADDITION.CODE= 6 then TABLE_ADDITION.VALUE end) Dest,
max(case when TABLE_ADDITION.CODE= 16 then TABLE_ADDITION.VALUE end) Mach2
FROM TABLE
This is working, the result is :
NAME Mach1 Source Dest Mach2
test 11 testS testD 12
I need another information from another table (MACH). Columns Mach1 and mach2 are IDs. I want to use this ID to take the name from the correct table MACH (see data below - end of the post).
I want to have :
NAME Mach1 Source Dest Mach2
test machName11 testS testD machName12
For that, I did :
select TABLE.NAME,
max(case when TABLE_ADDITION.CODE= 1 then MACH.MACHNAME end) Mach1,
max(case when TABLE_ADDITION.CODE= 4 then TABLE_ADDITION.VALUE end) Source,
max(case when TABLE_ADDITION.CODE= 6 then TABLE_ADDITION.VALUE end) Dest,
max(case when TABLE_ADDITION.CODE= 16 then MACH.MACHNAME end) Mach2
FROM TABLE
INNER JOIN TABLE_ADDITION ON TABLE.TABLEID = TABLE_ADDITION.TABLEID AND TABLE.NAME = TABLE_ADDITION.NAME
INNER JOIN MACH ON TABLE_ADDITION.CODE IN (1, 16) AND TABLE_ADDITION .VALUE = MACH.MACHID
However, I didn't receive my expected behavior :
NAME Mach1 Source Dest Mach2
test machName11 NULL NULL machName12
I tried for LEFT JOIN and INNER JOIN.
Data for TABLE_ADDITION :
TABLEID NAME CODE VALUE
1 test 1 11
1 test 4 testS
1 test 6 testD
1 test 16 12
1 test 20 value11
1 test 25 45
1 test ... [continue with a lot of ID and VALUE are int or varchar]
2 test2 1 45
2 test2 4 testSource\test
2 test2 6 testDest\test
2 test2 16 1
2 test2 20 value
2 test2 25 76
[continue for other ID]
For MACH
MACHID MACHNAME MACHTYPE
0 test 0
3 test1 1
10 test3 2
11 machName11 2
12 machName12 2
[continue with other ID]
For TABLE
TABLEID NAME TABLETYPE
1 test 12
1 test3 12
2 name 5
[continue with other ID]
I need the TABLE because it's my main table (with other column), I select some of them without issue.
EDIT, I edit my post, it was wrong and missing too much data to understand my issue.
For now it's working because I added one join :
select TABLE.NAME,
max(case when t2.CODE= 1 then MACH.MACHNAME end) Mach1,
max(case when TABLE_ADDITION.CODE= 4 then TABLE_ADDITION.VALUE end) Source,
max(case when TABLE_ADDITION.CODE= 6 then TABLE_ADDITION.VALUE end) Dest,
max(case when t2.CODE= 16 then MACH.MACHNAME end) Mach2
FROM TABLE
INNER JOIN TABLE_ADDITION ON TABLE.TABLEID = TABLE_ADDITION.TABLEID AND TABLE.NAME = TABLE_ADDITION.NAME
INNER JOIN TABLE_ADDITION t2 ON TABLE.TABLEID = t2 .TABLEID AND TABLE.NAME = t2 .NAME
INNER JOIN MACH ON t2 .CODE IN (1, 16) AND t2 .VALUE = MACH.MACHID
Thanks

Related

Convert Rows to columns using 'Pivot' Top 5

I want a pivot table from a SQL table with top 3 records only with filter based on user.
ID PrOjID User piD
------- ---- ------ ------
1 Prj1 ABC 1
2 Prj2 XYZ 2
3 Prj3 ABC 3
4 Prj4 ABC 4
5 Prj5 PQR 5
6 Prj1 XYZ 1
7 Prj3 PQR 3
8 Prj8 ABC 8
9 Prj1 PQR 1
10 Prj10 ABC 10
11 Prj11 ABC 11
12 Prj12 ABC 12
Result I want when user is ABC
ID1 PROJID1 piD1 ID2 PROJID2 piD2 ID3 PROJID3 piD3
1 prj1 1 3 PRJ3 3 4 prj4 4
If USER IS xyz
ID1 PROJID1 piD1 ID2 PROJID2 piD2 ID3 PROJID3 piD3
2 prj2 2 1 PRJ1 1 null null null
We can handle this using a pivot with the help of ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY piD) rn
FROM yourTable
)
SELECT
[User],
MAX(CASE WHEN rn = 1 THEN ID END) AS ID1,
MAX(CASE WHEN rn = 1 THEN PrOjID END) AS PROJID1,
MAX(CASE WHEN rn = 1 THEN piD END) AS piD1,
MAX(CASE WHEN rn = 2 THEN ID END) AS ID2,
MAX(CASE WHEN rn = 2 THEN PrOjID END) AS PROJID2,
MAX(CASE WHEN rn = 2 THEN piD END) AS piD2,
MAX(CASE WHEN rn = 3 THEN ID END) AS ID3,
MAX(CASE WHEN rn = 3 THEN PrOjID END) AS PROJID3,
MAX(CASE WHEN rn = 3 THEN piD END) AS piD3
FROM cte
WHERE
[User] = 'ABC'
GROUP BY
[User];
Demo

With multiple joins, can rows of one specific column be pivoted into one single row instead of pivoting into columns?

I am unable to pivot rows into one row of one column and unable to set alias column names
I have tried writing the join then putting that inside of a select and then pivoting that dataset.
select * from (
select DET.*, DETF.ExtractTemplateId, DetF.FieldId, DEF.Field from DataExtractTemplate DET
join DataExtractTemplateFields DETF
on DET.Id = DETF.ExtractTemplateId
join DataExtractFields DEF
on DETF.FieldId = DEF.Id
WHERE ClientId = 1) AS Src
PIVOT (
sum(Id)
for FieldId in ([1],[2],[6],[7])
) Pvt
I am getting this:
Field 1 2 6 7
____________________________________________
First Name 1 NULL NULL NULL
Last Name NULL 1 NULL NULL
NPI NULL NULL 1 NULL
Phone Number NULL NULL NULL 1
but I want this
Field1 Field2 Field6 Field7
____________________________________
First Name Last Name NPI Phone Number
Screenshot of ERD
It's not exactly easy to understand what you're trying to do, but it seems that using a cross-tab query could help you.
SELECT SomeGroupingColumns,
MAX(CASE WHEN DetF.FieldId = 1 THEN DEF.Field END) AS Field1,
MAX(CASE WHEN DetF.FieldId = 2 THEN DEF.Field END) AS Field2,
MAX(CASE WHEN DetF.FieldId = 6 THEN DEF.Field END) AS Field6,
MAX(CASE WHEN DetF.FieldId = 7 THEN DEF.Field END) AS Field7
FROM DataExtractTemplate DET
JOIN DataExtractTemplateFields DETF ON DET.Id = DETF.ExtractTemplateId
JOIN DataExtractFields DEF ON DETF.FieldId = DEF.Id
WHERE ClientId = 1
GROUP BY SomeGroupingColumns;
This code worked! However, with my updated code, I am getting nulls
SELECT DET.*,
MAX(CASE WHEN (DetF.FieldId IS NOT NULL AND DETF.FieldID = 1) THEN DETF.FieldId END) AS Field,
MAX(CASE WHEN DetF.FieldId IS NOT NULL AND DETF.FieldID = 2 THEN DETF.FieldId END) AS Field,
MAX(CASE WHEN (DetF.FieldId IS NOT NULL AND DETF.FieldID = 3) THEN DETF.FieldId END) AS Field,
MAX(CASE WHEN DetF.FieldId IS NOT NULL AND DETF.FieldID = 4 THEN DETF.FieldId END) AS Field,
MAX(CASE WHEN DetF.FieldId IS NOT NULL AND DETF.FieldID = 5 THEN DETF.FieldId END) AS Field,
MAX(CASE WHEN DetF.FieldId IS NOT NULL AND DETF.FieldID = 6 THEN DETF.FieldId END) AS Field,
MAX(CASE WHEN DetF.FieldId IS NOT NULL AND DETF.FieldID = 7 THEN DETF.FieldId END) AS Field,
MAX(CASE WHEN DetF.FieldId IS NOT NULL AND DETF.FieldID = 8 THEN DETF.FieldId END) AS Field
FROM DataExtractTemplate DET
JOIN DataExtractTemplateFields DETF ON DET.Id = DETF.ExtractTemplateId
JOIN DataExtractFields DEF ON DETF.FieldId = DEF.Id
WHERE ClientId = 1 and DETF.FieldId IS NOT NULL
GROUP BY DET.Id, DET.ClientId, DET.Name, DET.Description, DET.Delimiter, DET.id, DET.FieldQuotes, DET.ExportFormat, DET.DataSetType,
DET.DeliveryEmail, Det.DeliveryMethod, DET.RecurrenceDayOfYear, DET.RecurrenceDaysOfMonth, DET.RecurrenceEndType, DET.RecurrencePattern, DET.RecurrenceRangeEnd, DET.RecurrenceRangeEndAfter,
DET.RecurrenceRangeStart, Det.RecurrenceWeeks, DET.TimesRecurred, DET.Active;
Row showing nulls

Operand data type image is invalid for max operator in SQL Server 2014

I have a query that works in dev 2008 but does not work in test 2014.
I need the query returned in the exact format due to display requiremnts, but I don't know how to convert it. I tried casting and converting.
The error message i get on 2014 when i run the query is
Msg 8117, Level 16, State 1, Line 3
Operand data type image is invalid for max operator.
Here is the query:
SELECT Max(CASE
WHEN rn % 3 = 0 THEN itemtransactionbatchid
END) AS ItemTransactionBatchId,
Max(CASE
WHEN rn % 3 = 0 THEN referencebytes
END) AS ReferenceBytes,
Max(CASE
WHEN rn % 3 = 0 THEN description
END) AS Description,
Max(CASE
WHEN rn % 3 = 1 THEN itemtransactionbatchid
END) AS ItemTransactionBatchId1,
Max(CASE
WHEN rn % 3 = 1 THEN referencebytes
END) AS ReferenceBytes1,
Max(CASE
WHEN rn % 3 = 1 THEN description
END) AS Description1,
Max(CASE
WHEN rn % 3 = 2 THEN itemtransactionbatchid
END) AS ItemTransactionBatchId2,
Max(CASE
WHEN rn % 3 = 2 THEN referencebytes
END) AS ReferenceBytes2,
Max(CASE
WHEN rn % 3 = 2 THEN description
END) AS Description2
FROM (SELECT a.itemtransactionbatchid,
a.referencebytes,
b.description,
( ROW_NUMBER()
OVER(
ORDER BY CASE WHEN b.code='SIGOPRT' THEN 1 WHEN b.code='SIGDRVR' THEN 2 WHEN b.code='SIGTRANS' THEN 3 WHEN b.code='SIGRECV' THEN 4 WHEN b.code='SIGN' THEN 5 WHEN b.code='SIGSUPR' THEN 6 ELSE 0 END, b.code, (SELECT NULL)) - 1 ) rn
FROM [Transaction].itemtransactionref a (NOLOCK)
JOIN [Transaction].transactionreftype b
ON a.transactionreftypeid = b.transactionreftypeid
WHERE b.code IN( 'SIGDRVR', 'SIGN', 'SIGOPRT', 'SIGRECV',
'SIGSUPR', 'SIGTRANS' )
AND a.itemtransactionbatchid = xxxxxxx
AND referencebytes IS NOT NULL)x
GROUP BY rn / 3
Change the datatype of the image column to VARBINARY(MAX); MAX on that type is supported.
This does not give any errors:
CREATE TABLE #t(entr VARBINARY(MAX));
SELECT MAX(entr) FROM #t;

How to fetch record from two tables specify column name based on second table row records

I need query which fetch records from two tables but column name should be based on records in second table.
Details are below
My first table
Emp Table
emp_id emp_name
1 Abc
2 XYZ
3 PQR
My second table
Salary Table
id emp_id month salary
1 1 1 4000
2 1 2 3000
3 2 1 5000
4 2 2 4500
I need output like,
emp_id emp_name jan feb
1 Abc 4000 3000
2 XYZ 5000 4500
I am able to achieve this by using left join but for every month I need to add it in query like,
select e.emp_id,e.emp_name,j.month as Jan,f.month as Feb from emp e
Left Join salary j on e.emp_id=j.emp_id and j.month=1
Left Join salary f on e.emp_id=f.emp_id and f.month=2
Above work for me But which is not feasible. I have master table for month also.
Month Table
id Name
1 Jan
2 Feb
3 March
5 April
I want fetch record for for specific month currently for (Jan & feb).
Please help me achieve this faster way.
Using conditional aggregation:
SELECT
e.emp_id,
e.emp_name,
[Jan] = MAX(CASE WHEN s.[month] = 1 THEN s.salary END),
[Feb] = MAX(CASE WHEN s.[month] = 2 THEN s.salary END),
[Mar] = MAX(CASE WHEN s.[month] = 3 THEN s.salary END),
[Apr] = MAX(CASE WHEN s.[month] = 4 THEN s.salary END),
[May] = MAX(CASE WHEN s.[month] = 5 THEN s.salary END),
[Jun] = MAX(CASE WHEN s.[month] = 6 THEN s.salary END),
[Jul] = MAX(CASE WHEN s.[month] = 7 THEN s.salary END),
[Aug] = MAX(CASE WHEN s.[month] = 8 THEN s.salary END),
[Sep] = MAX(CASE WHEN s.[month] = 9 THEN s.salary END),
[Oct] = MAX(CASE WHEN s.[month] = 10 THEN s.salary END),
[Nov] = MAX(CASE WHEN s.[month] = 11 THEN s.salary END),
[Dec] = MAX(CASE WHEN s.[month] = 12 THEN s.salary END)
FROM Emp e
LEFT JOIN Salary s
ON s.emp_id = e.emp_id
GROUP BY
e.emp_id, e.emp_name
ONLINE DEMO

SQL PIVOT on a variable amount of rows

I have the following data on a MSSQL Server:
Item No_ Unit Of Measure Qty Per Base UoM Rounding Precision
000001 PIECE 1 1.0
000001 PALLET 100 1.0
000001 BOX 12 1.0
000002 KG 1 1.0
000002 TON 1000 0.001
I am trying to get the following output:
Item No_ UoM1 Qty pb UoM1 RP1 UoM2 Qty pb UoM2 RP2 UoM3 Qty pb UoM3 RP3
000001 PIECE 1 1.0 PALLET 100 1.0 BOX 12 1.0
000002 KG 1 1.0 TON 1000 0.0001 NULL NULL NULL
I tried achieving this using the PIVOT operator but it does not seem te be correct.
What is the correct way to achieve my desired output?
For trully generic solution you need to use Dynamic-SQL.
But you say you want starting point, so I give you one. You can use:
LiveDemo
WITH cte AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY Item_No_ ORDER BY (SELECT 1)) AS rn
FROM #mytable
)
select Item_No_,
max(case when rn = 1 then Unit_Of_Measure end) UoM1,
max(case when rn = 1 then Qty_Per_Base_UoM end) [Qty pb UoM1],
max(case when rn = 1 then Rounding_Precision end) RP1,
max(case when rn = 2 then Unit_Of_Measure end) UoM2,
max(case when rn = 2 then Qty_Per_Base_UoM end) [Qty pb UoM2],
max(case when rn = 2 then Rounding_Precision end) RP2,
max(case when rn = 3 then Unit_Of_Measure end) UoM3,
max(case when rn = 3 then Qty_Per_Base_UoM end) [Qty pb UoM3],
max(case when rn = 3 then Rounding_Precision end) RP3,
max(case when rn = 4 then Unit_Of_Measure end) UoM4,
max(case when rn = 4 then Qty_Per_Base_UoM end) [Qty pb UoM4],
max(case when rn = 4 then Rounding_Precision end) RP4
from cte
group by Item_No_;
The point is that if your number of units is known in advance you can create hardcoded columns from 1 .. n.
For more info search Dynamic Pivot multiple columns. It is achievable, but first try to crack this solution.

Resources