Cell to Cell comparison in Sql Server? - sql

I have tbl1 :
Id | c1 | c2 | c3 |
____|_____|______|_______|_
1 a b c
____|_____|______|_______|_
2 h j k
____|_____|______|_______|_
3 t y u
____|_____|______|_______|_
I have tbl2 :
Id | c1 | c2 | c3 |
____|_____|______|_______|_
1 a b D
____|_____|______|_______|_
2 c c c
____|_____|______|_______|_
3 k l k
____|_____|______|_______|_
I need to compare each cell from tbl1 to its appropriate place in tbl2 :
the desired output is :
Id |tbl1 | tbl2 |
____|_____|______|
1 a a
____|_____|______|
1 b b
____|_____|______|
1 c d
____|_____|______|
2 h c
____|_____|______|
2 j c
____|_____|______|
2 k c
____|_____|______|
...
...
...
...
visual representation :
i tried many queries... but not succeed...

select T1.id, T1.tbl1, T2.tbl2
from (
select U.id, U.tbl1, U.col
from tbl1
unpivot (tbl1 for col in (c1, c2, c3)) U
) T1
inner join
(
select U.id, U.tbl2, U.Col
from tbl2
unpivot (tbl2 for col in (c1, c2, c3)) U
) T2
on T1.id = T2.id and
T1.col = T2.col
order by T1.id

First you should unpivot data:
select Id, C1, 'C1' as C from tbl1 union all
select Id, C2, 'C2' as C from tbl1 union all
select Id, C3, 'C2' as C from tbl1 union all
Then you can compare data:
select coalesce( uTbl1.Id,uTbl2.Id) as Id, uTbl1.C, uTbl2.C
from (
select Id, C1 as C, 'C1' as T from tbl1 union all
select Id, C2 as C, 'C2' as T from tbl1 union all
select Id, C3 as C, 'C3' as T from tbl1 ) uTbl1
full outer join (
select Id, C1 as C, 'C1' as T from tbl2 union all
select Id, C2 as C, 'C2' as T from tbl2 union all
select Id, C3 as C, 'C3' as T from tbl2 ) uTbl2
on uTbl1.Id = uTbl2.Id and uTbl1.T = uTbl2.T
Disclaimer:
- Not tested.
Edited With CTE:
; with
uTbl1 as (
select Id, C1 as C, 'C1' as T from tbl1 union all
select Id, C2 as C, 'C2' as T from tbl1 union all
select Id, C3 as C, 'C3' as T from tbl1 )
,uTbl2 as (
select Id, C1 as C, 'C1' as T from tbl2 union all
select Id, C2 as C, 'C2' as T from tbl2 union all
select Id, C3 as C, 'C3' as T from tbl2 )
select coalesce( uTbl1.Id,uTbl2.Id) as Id, uTbl1.C, uTbl2.C
from
uTbl1
full outer join
uTbl2
on uTbl1.Id = uTbl2.Id and uTbl1.T = uTbl2.T

Do 3 atomic subqueries and use then with UNION ALL to get the final result:
SELECT tbl1.id, tbl1.c1, tbl2.c1 FROM tbl1
INNER JOIN tbl2 on tbl1.id = tbl2.id
UNION ALL
SELECT tbl1.id, tbl1.c2, tbl2.c2 FROM tbl1
INNER JOIN tbl2 on tbl1.id = tbl2.id
UNION ALL
SELECT tbl1.id, tbl1.c3, tbl2.c3 FROM tbl1
INNER JOIN tbl2 on tbl1.id = tbl2.id
ORDER BY 1 --sort by column 1 (the IDs)

Related

Fill a select with null when join isn't possible

I'm trying to do a select in n tables and show a few columns of each, but sometimes I can't match some columns and instead of getting a line with "null" the entire line is omitted.
For example:
table_a
id
...
1
2
3
table_b
id
name
...
1
a1
...
2
b2
...
3
c3
...
table_c
name
...
a1
...
And then I do the following select:
select
a.id,
c.name
from
table_a a,
table_b b,
table_c
where
( 1 = 1 )
and a.id = b.id
and b.name = c.name
I'm geting:
id
name
...
1
a1
...
I'm looking for:
id
name
...
1
a1
...
2
null
...
3
null
...
How do I do that? I checked a few answers around including this one but I didn't get how to solve it.
You can use an OUTER JOIN:
SELECT a.id,
c.name
FROM table_a a
LEFT OUTER JOIN table_b b
ON (a.id = b.id)
LEFT OUTER JOIN table_c c
ON (b.name = c.name)
or, depending on precedence of the joins:
SELECT a.id,
c.name
FROM table_a a
LEFT OUTER JOIN (
table_b b
INNER JOIN table_c c
ON (b.name = c.name)
)
ON (a.id = b.id)
Which, for the sample data:
CREATE TABLE table_a (id) AS
SELECT 1 FROM DUAL UNION ALL
SELECT 2 FROM DUAL UNION ALL
SELECT 3 FROM DUAL;
CREATE TABLE table_b (id, name) AS
SELECT 1, 'a1' FROM DUAL UNION ALL
SELECT 2, 'b1' FROM DUAL UNION ALL
SELECT 3, 'c1' FROM DUAL;
CREATE TABLE table_c (name) AS
SELECT 'a1' FROM DUAL;
Would both output:
ID
NAME
1
a1
2
null
3
null
fiddle
You should use a left join, not sure on oracle specifically but it would look something like:
select
a.id,
c.name
from
table_a a
LEFT JOIN table_b b ON (a.id = b.id)
LEFT JOIN table_c c ON (b.name = c.name)

How to combine multiple tables with the basic ID of one table

I want to combine 5 multiple tables, that have the same reference ID as the basic table containing all IDs. The "joined" tables are not containing a value for every reference, but sometimes they have multiple values for one reference. The output should be a sum of each value of the ID.
Example:
Basic Table:
Reference
Basic.Value
1
a
2
b
3
c
4
d
5
e
6
f
7
g
8
h
Table 1:
Reference
T1.Value
1
i
2
j
2
x
3
k
4
l
Table 2
Reference
T2.Value
1
m
5
n
7
o
7
y
8
p
Table 3
Reference
T3.Value
2
q
4
r
6
s
8
t
8
z
Result that should be the output:
Reference
Basic.Value
SUM(T1.Value)
SUM(T2.Value)
SUM(T3.Value)
1
a
i
m
2
b
(j+x)
q
3
c
k
4
d
l
r
5
e
n
6
f
s
7
g
(o+y)
8
h
p
(t+z)
I tried the following code:
SELECT
T0."STATUS",
T0."DocNum" AS "ProjectNumber",
T0."NAME", T0."CARDNAME" AS "Client",
T0."FINISHED" AS "Project Finished",
T1."PoPhAmt" AS "Project Value",
T1."PhBudget" AS "Budget",
(T1."PoPhAmt"-T1."PhBudget") AS "Planned Gross Profit",
T1."TotalAP" AS "Ordered",
SUM(T2."PaidSys") AS "Paid Downpayments(Client)",
COUNT(T2."PaidSys"),
SUM(T3."PaidSys") AS "Paid Invoices(Client)",
COUNT(T3."PaidSys"),
SUM(T4."PaidSys") AS "Creditnotes(Client)",
COUNT(T4."PaidSys")
FROM
(OPMG T0 INNER JOIN PMG8 T1 ON T0."AbsEntry" = T1."AbsEntry")
LEFT JOIN ODPI T2 ON T0."FIPROJECT" = T2."Project"
LEFT JOIN OINV T3 ON T0."FIPROJECT" = T3."Project"
LEFT JOIN ORIN T4 ON T0."FIPROJECT" = T4."Project"
WHERE
T0."FINISHED" < '100' AND T0."STATUS" <> 'N' AND T0."STATUS" <> 'P'
GROUP BY
T0."STATUS",
T0."DocNum",
T0."NAME",
T0."CARDNAME",
T0."FINISHED" ,
T1."PoPhAmt",
T1."PhBudget",
T1."TotalAP"
ORDER BY
T0."DocNum"
Aggregate before joining:
select *
from basic_table t left join
(select t1.project, count(*) as cnt1, sum(value) as value1
from t1
group by t1.project
) t1
on t.FIPROJECT = T1.Project left join
(select t2.project, count(*) as cnt2, sum(value) as value2
from t2
group by t2.project
) t2
on t.FIPROJECT = T2.Project left join
(select t3.project, count(*) as cnt3, sum(value) as value3
from t3
group by t3.project
) t3
on t.FIPROJECT = T3.Project;
SELECT T.ID,T.VALUE,T1.VALUE T_1_VALUE,T2.VALUE T_2_VALUE,T3.VALUE T_3_VALUE
FROM BASIC_TABLE T
LEFT JOIN TABLE_1 T1 ON T.ID=T1.ID
LEFT JOIN TABLE_2 T2 ON T.ID=T2.ID
LEFT JOIN TABLE_3 T3 ON T.ID=T3.ID
WITH BASIC_TABLE(REFERENCE,BASIC_VALUE) AS
(
SELECT 1, 'a' UNION ALL
SELECT 2 , 'b' UNION ALL
SELECT 3 , 'c' UNION ALL
SELECT 4 , 'd' UNION ALL
SELECT 5 , 'e' UNION ALL
SELECT 6 , 'f' UNION ALL
SELECT 7 , 'g' UNION ALL
SELECT 8 , 'h'
),
TABLE_1(REFERENCE,T1_VALUE) AS
(
SELECT 1, 'i' UNION ALL
SELECT 2, 'j' UNION ALL
SELECT 2, 'x' UNION ALL
SELECT 3, 'k' UNION ALL
SELECT 4, 'l'
),
TABLE_2(REFERENCE,T2_VALUE)AS
(
SELECT 1, 'm' UNION ALL
SELECT 5, 'n' UNION ALL
SELECT 7, 'o' UNION ALL
SELECT 7, 'y' UNION ALL
SELECT 8 , 'p'
),
TABLE_3(REFERENCE,T3_VALUE)AS
(
SELECT 2, 'q' UNION ALL
SELECT 4, 'r' UNION ALL
SELECT 6, 's' UNION ALL
SELECT 8, 't' UNION ALL
SELECT 8, 'z'
)
SELECT B.REFERENCE,B.BASIC_VALUE,ISNULL(T1.R,'')AS SUM_T_1_VALUE,ISNULL(T2.R,'')AS SUM_T_2_VALUE,
ISNULL(T3.R,'')AS SUM_T_3_VALUE
FROM BASIC_TABLE AS B
LEFT JOIN
(
SELECT T.REFERENCE,STRING_AGG(T.T1_VALUE,'+')R
FROM TABLE_1 AS T
GROUP BY T.REFERENCE
)T1 ON B.REFERENCE=T1.REFERENCE
LEFT JOIN
(
SELECT T.REFERENCE,STRING_AGG(T.T2_VALUE,'+')R
FROM TABLE_2 AS T
GROUP BY T.REFERENCE
)T2 ON B.REFERENCE=T2.REFERENCE
LEFT JOIN
(
SELECT T.REFERENCE,STRING_AGG(T.T3_VALUE,'+')R
FROM TABLE_3 AS T
GROUP BY T.REFERENCE
)T3 ON B.REFERENCE=T3.REFERENCE
Not sure about SAP HANA, but in MS SQL Server 2017 this code produces more or less the required output
use following query STRING_AGG function with group by Basic_Table.Reference
SELECT
T.Reference,
MAX(T.Basic_Value) AS Basic_Value,
SUM(T1.T1_Value) AS T1_Value,
SUM(T2.T2_Value) AS T2_Value,
SUM(T3.T3_Value) AS T3_Value
FROM BASIC_TABLE T
LEFT JOIN TABLE_1 T1 ON T.Reference=T1.Reference
LEFT JOIN TABLE_2 T2 ON T.Reference=T2.Reference
LEFT JOIN TABLE_3 T3 ON T.Reference=T3.Reference
GROUP BY T.Reference

How do you join two tables A and B in order to get a non join column in A with data not in B?

I'd like to do a join across the following two tables that would help identify all of the Customers that have Attributes they are missing. A full outer join on Attributes doesn't work since the null values don't correspond to any customer.
One option is to group by Customers to get a count of distinct attributes and compare that with count of attributes. That would give Customers that have discrepancies, but wanted underlying attributes missed. Is this possible?
Table A (Customer to Attributes)
-----------
C1 | ATTR_1
C1 | ATTR_2
C1 | ATTR_3
C2 | ATTR_1
C2 | ATTR_2
C3 | ATTR_3
Table B (Attributes)
-------
ATTR_1
ATTR_2
ATTR_3
Output
------
C2 | ATTR_3
C3 | ATTR_1
C3 | ATTR_2
Do a cross join to get all combinations. Use except to remove the existing ones:
SELECT DISTINCT ta.Customer, tb.Attributes
FROM tableA ta CROSS JOIN tableB tb
EXCEPT
SELECT Customer, Attributes
FROM tableA
If you have a customers table, I would use that:
select c.cust, a.attr
from customers c cross join join
attributes a left join
customer_attributes ca
on c.cust = ca.cust and a.ttr = ca.attr
where ca.cust is null;
Hope Can Help You
Select * Into #Cust From (
Select 'C1' [IDCustomer], 'ATTR_1' [IDAttributes] Union All
Select 'C1' [IDCustomer], 'ATTR_2' [IDAttributes] Union All
Select 'C1' [IDCustomer], 'ATTR_3' [IDAttributes] Union All
Select 'C2' [IDCustomer], 'ATTR_1' [IDAttributes] Union All
Select 'C2' [IDCustomer], 'ATTR_2' [IDAttributes] Union All
Select 'C3' [IDCustomer], 'ATTR_3' [IDAttributes]
) A
Select * Into #Attr From (
Select 'ATTR_1' [IDAttributes] Union All
Select 'ATTR_2' [IDAttributes] Union All
Select 'ATTR_3' [IDAttributes]
) A
Select C.IDCustomer, A.IDAttributes From (
Select IDCustomer From #Cust
Group By IDCustomer
) C
Left Join #Attr A On 1 = 1
Left Join #Cust D On D.IDCustomer = C.IDCustomer And D.IDAttributes = A.IDAttributes
Where D.IDCustomer Is Null
(Assuming a customers table) reformulating the cross-join:
SELECT c.cust, a.attr
FROM customers c
JOIN attributes a
ON NOT EXISTS (
SELECT *
FROM customer_attributes ca
WHERE ca.cust = c.cust AND ca.attr = a.attr
);

Return matching rows only SQL Server

I am sure this simple but i am really stuck. Here is a example of the resultset i want from two tables that have the same structure and in this case data or records
TableA
Ref cola colb id
------------------
1 a b 14
1 a b 24
TableB
Ref cola colb id
------------------
1 a b 1
1 a b 2
1 a b 3
Expected result:
Ref cola colb id Ref1 cola1 colb1 id1
----------------------------------------
1 a b 14 1 a b 1
1 a b 24 1 a b 2
Use:
SELECT *
FROM table1 t1
JOIN Table2 t2
ON t1.Ref =t2.Ref AND t1.cola = t2.cola
AND t1.colb = t2.colb AND t1.id = t2.id
or
SELECT *
FROM table1 t1
JOIN Table2 t2
USING ( Ref , cola , colb, id )
one more way would be
;with cte
as
(
select Ref, cola, colb, id,
hashbytes('sha1',concat(Ref, cola, colb)) as tb1hash
from table1
)
select
t1.Ref, --all required cols
from cte c
join
(
select Ref, cola, colb, id,
hashbytes('sha1',concat(Ref, cola, colb)) as tb2hash
from table2
) b
on
b.tb2hash=c.tb1hash
Guessing:
;WITH TableAWithRowNum
AS (
SELECT *, ROW_NUMBER(ORDER BY id) AS RowNum
FROM dbo.TableA
), TableBWithRowNum
AS (
SELECT *, ROW_NUMBER(ORDER BY id) AS RowNum
FROM dbo.TableB
)
SELECT a.*, b.*
FROM TableAWithRowNum a
INNER JOIN TableBWithRowNum b ON a.Ref = b.Ref
--AND other join predicates on ColA, ... etc.
AND a.RowNum = b.RowNum

Select only rows that have unique fields

What is an SQL command that checks for rows that have rows with no duplicate fields in them.
ex:
A A A B B B should not be in the resulting table.
Only rows such as A B C D E F
i.e. given data like:
A A A B B B
A B C D E F
A A B G H Q
Should return A B C D E F
There is no simple command to do this.
is seems an unusual requirement and possibly an indication that the table is not in first normal form if all columns are interchangeable.
The following works in Microsoft SQL Server
;With YourData AS
(
select 'A' as C1, 'A' as C2, 'A' as C3, 'B' as C4, 'B' as C5, 'B' as C6 UNION ALL
select 'A' as C1, 'B' as C2, 'C' as C3, 'D' as C4, 'E' as C5, 'F' as C6
)
SELECT *
FROM YourData
WHERE 1 =
( SELECT TOP 1 COUNT(*) AS Cnt
FROM (
SELECT C1 AS C
UNION ALL
SELECT C2
UNION ALL
SELECT C3
UNION ALL
SELECT C4
UNION ALL
SELECT C5
UNION ALL
SELECT C6
) D
GROUP BY C
ORDER BY Cnt DESC
)
Select distinc * returns unique ROWS not unique values from fields.
You should compare each column's value with others. (Assuming column types are the same). For example, for a 4 column table you should do smoething like:
SELECT Col1, Col2, Col3, Col4 FROM MyTable WHERE
Col1 NOT IN (Col2,Col3,Col4) AND
Col2 NOT IN (Col3,Col4) AND
Col3 <> Col4
SELECT DISTINCT * FROM tablename
SELECT DISTINCT col FROM tabl
SELECT * FROM
mytable
WHERE mytable.col1 != mytable.col2 != mytable.col3 ...