SQL Query to merge several views into one - sql

I was trying to create a new view out of 3 or 4 other views/tables.
TableA:
title_id
homeTeam
1234
WSV
5678
SSV
7890
NULL
4321
SCC
TableB:
title_id
awayTeam
1234
SSV
5678
SFV
7890
NULL
4321
KFC
TableC:
title_id
homeTeam
1234
SSV
5678
NULL
7890
AAB
4711
BFG
I would like to generate a new view out of those three which looks like:
title_id
Teams
1234
WSV, SSV, SSV
5678
SSV, SFV, N/A
7890
N/A, N/A, AAB
4321
SCC, KFC, N/A
4711
N/A, N/A, BFG
As you can see, NULL should be renamed to N/A, as well if id doesn't exist in one of the other tables. And I would like to get DISTINCT title_id.
#DaleK sure, i tried it like this:
select tableA.title_id, ISNULL(tableA.homeTeam, 'N/A') + ',' +
ISNULL(tableB.awayTeam, 'N/A') + ',' + ISNULL(tableC.homeTeam, 'N/A')
as Teams from tableA, tableB, tableC;
This leads into an neverending query for my tables which has each more than 300k rows.
Next i tried join:
select tableA.title_id, ISNULL(tableA.homeTeam, 'N/A') + ',' +
ISNULL(tableB.awayTeam, 'N/A') + ',' + ISNULL(tableC.homeTeam, 'N/A')
as Teams from tableA FULL JOIN tableB ON tableB.title_id =
tableA.title_id FULL JOIN tableC ON tableC.title_id = tableA.tile_id
But to be honest i wasnt sure about the number of rows.

You can UNION ALL the tables together, then use string aggregation
SELECT
t.title_id,
STRING_AGG(ISNULL(t.team, 'N/A'), ', ') WITHIN GROUP (ORDER BY t.ordering) AS team
FROM (
SELECT
a.title_id,
a.homeTeam AS team,
1 AS ordering
FROM TableA a
UNION ALL
SELECT
b.title_id,
b.awayTeam,
2
FROM TableB b
UNION ALL
SELECT
c.title_id,
c.homeTeam,
3
FROM TableC c
) t
GROUP BY
t.title_id;
For SQL Server 2016 and earlier, you have to use the FOR XML method, and it's less efificent as you have to query the tables multiple times
WITH t AS (
SELECT
a.title_id,
a.homeTeam AS team,
1 AS ordering
FROM TableA a
UNION ALL
SELECT
b.title_id,
b.awayTeam,
2
FROM TableB b
UNION ALL
SELECT
c.title_id,
c.homeTeam,
3
FROM TableC c
)
SELECT
tOuter.title_id,
STUFF(tInner.team.value('text()[1]', 'nvarchar(max)'), 1, LEN(', '), '') AS team
FROM (
SELECT DISTINCT t.title_id
FROM t
) tOuter
CROSS APPLY (
SELECT ', ' + ISNULL(t.team, 'N/A')
FROM t
WHERE t.title_id = tOuter.title_id
ORDER BY t.ordering
FOR XML PATH(''), TYPE
) tInner(team);
db<>fiddle

Try this:
select
COALESCE(a.title_id,b.title_id,c.title_id),
CONCAT(
ISNULL(a.homeTeam,'N/A'),
ISNULL(b.awayTeam,'N/A'),
ISNULL(c.homeTeam,'N/A'),
) 'Teams',
from TableA a
full join TableB b on a.title_id = b.title_id
full join TableC c on c.title_id = a.title_id
where
a.homeTeam is not null
OR b.awayTeam is not null
OR c.homeTeam is not null
group by a.title_id
As for the DISTINCT title_id, it should be unique by default as I assume it is used as the key in each of the tables.

Related

how to add two columns as result in single query

I have below queries
select a.emp_id,a.AUTH_TYPE,b.NTE_TX as des1
from table a inner join NOTES b on b.TBL_ROW_ID=a.emp_id
where a.emp_id=56 and REF_NTE_TYP_ID=27
Output 1
select a.emp_id,a.AUTH_TYPE,b.NTE_TX as des2
from table a inner join NOTES b on b.TBL_ROW_ID=a.emp_id
where a.emp_id=56 and REF_NTE_TYP_ID=28
Output 2
Expected Output:
please help any one.
Simple Aggregation(MAX) will help you to get your expected output.
Try this:
select a.emp_id,a.AUTH_TYPE
,MAX(CASE WHEN REF_NTE_TYP_ID=27 THEN b.NTE_TX END) as des1
,MAX(CASE WHEN REF_NTE_TYP_ID=28 THEN b.NTE_TX END) as des2
from table a inner join NOTES b on b.TBL_ROW_ID=a.emp_id
where a.emp_id=56 and REF_NTE_TYP_ID IN(27,28)
GROUP BY a.emp_id,a.AUTH_TYPE
With Q1 As (
select 56 emp_id, 'diple' auth_type
),
Q2 As (
Select 'text2' Des2,27 ref_nte_type_id, 56 row_id
Union All
Select 'text1' Des2,28 ref_nte_type_id, 56 row_id
)
Select Q1.*,Q2.Des2,Q3.Des2 Des1
From Q1
Inner Join Q2
On Q1.Emp_Id=Q2.Row_Id
And Q2.Ref_Nte_Type_Id=27
Inner Join Q2 Q3
On Q1.Emp_Id=Q3.Row_Id
And Q3.Ref_Nte_Type_Id=28
If TBL_ROW_ID, REF_NTE_TYP_ID is unique in your table NOTESyou can also use subqueries:
select a.emp_id,a.AUTH_TYPE
, (SELECT b.NTE_TX
FROM NOTES b
WHERE b.TBL_ROW_ID=a.emp_id
AND REF_NTE_TYP_ID=27) as des1
, (SELECT b.NTE_TX
FROM NOTES b
WHERE b.TBL_ROW_ID=a.emp_id
AND REF_NTE_TYP_ID=28) as des2
from table a
where a.emp_id=56
If you have multiple text-entries you might want to concatenate these entries to just print one long text (replace the 2 occurences of SELECT b.NTE_TX with the following):
SELECT RTRIM(XMLAGG(XMLELEMENT(b.NTE_TX, CHR(10)).EXTRACT('//text()') ORDER BY b.NTE_TX).GetClobVal(),CHR(10))
I used CHR(10) as text delimiter, just replace it with any other string you want. And you might also want some other ORDER BYcondition.

SQL query multiple rows into single row that has JOIN

I am trying to combine multiple rows into a single row that involves a JOIN. I cannot figure how to get the JOIN piece to work.
I am on SQL Server 2014.
This piece works great where I am rolling rows into a single comma separated line based on ID_REVIEW:
SELECT DISTINCT
ID_REVIEW
, STUFF((
SELECT N', ' + CAST(AREA_ID AS VARCHAR(255))
FROM AREA_ASSOC t2
WHERE t1.ID_REVIEW = t2.ID
FOR XML PATH('')
), 1, 1, '') AS AREA_ID
FROM REQUEST_WORKLOAD t1
Result:
ID_REVIEW | AREA_ID
-----------------
11438 | 2
23501 | 10, 15
44677 | 8
What I'd like to do is instead of having numbers for AREA_ID is have the name of that area show up. The goal being to have:
ID_REVIEW | AREA_NM
-----------------
11438 | State St.
23501 | Main St., Second St.
44677 | Adams Ave.
This AREA_NM information is contained in another table, called AREA. In a separate query, I can do a LEFT JOIN on table AREA_ASSOC to pull in the AREA_NM:
SELECT DISTINCT
[AREA_NM]
FROM AREA_ASSOC
LEFT JOIN AREA ON
AREA_ASSOC.AREA_ID = AREA.AREA_ID
I'm stumped as to how to get that JOIN into the STUFF function so I can get the area names. Is there a way to do this?
Do the join in the subquery:
SELECT DISTINCT r2.ID_REVIEW,
STUFF( (SELECT N', ' + a2AREA_NM
FROM AREA_ASSOC aa2 JOIN
AREA a
ON aa2.AREA_ID = A.AREA_ID
WHERE aa2.ID_REVIEW = r2.ID
FOR XML PATH('')
), 1, 2, ''
) AS AREA_ID
FROM REQUEST_WORKLOAD rw

How to update a table joined with another table multiple times in Oracle?

I have three fields in my table and I want to update them by joining three times to another table. I know that I have to use merge into, but I couldn't find any similar query that uses merge into and join with only one table for multiple times.
The select statement is something like this:
select * from TABLE t
inner join DESTINATION_TABLE d1
on t.CODE1 = d1.CODE
inner join DESTINATION_TABLE d2
on t.CODE2 = d2.CODE
inner join DESTINATION_TABLE d3
on t.CODE3 = d3.CODE
Now how can I update three fields (FIELD1, FIELD2, FIELD3) from TABLE by using fields from d1, d2, and d3 using merge into?
EDIT:
The original query is:
select * from TOTAL
inner join GROUP_LEVEL_DETAIL gl1
on gl1.NAME = substr(GL, 1, instr(GL, ' -', 1))
inner join GROUP_LEVEL_DETAIL gl2
on GL2.NAME = replace(substr(GL, instr(GL, ' -', 1, 1), instr(GL, ' -', 1, 2) - instr(GL, ' -', 1, 1)), ' - ', '')
inner join GROUP_LEVEL_DETAIL gl3
on gl3.NAME = replace(substr(GL, instr(GL, '-', 1, 2), 500), '- ', '')
The sample data for TOTAL is:
ID GL GL1_CODE GL2_CODE GL3_CODE
----- ----------------------------- ---------- ---------- -----------
1 Sample1 - Sample2 - Sample3 null null null
2 John - Jack - Harry null null null
The sample data for GROUP_LEVEL_DETAIL is:
CODE NAME LEVEL_NO
--------- ----------- ------------
SMP1 Sample1 1
SMP2 Sample2 2
SMP3 Sample3 3
JCK1 Jack 1
JHN2 John 2
HRY3 Harry 3
And I want my TOTAL table get like this after the update:
ID GL GL1_CODE GL2_CODE GL3_CODE
----- ----------------------------- ---------- ---------- -----------
1 Sample1 - Sample2 - Sample3 SMP1 SMP2 SMP3
2 John - Jack - Harry JCK1 JHN2 HRY3
From your revised question, I think the solution is to assemble the GROUP_LEVEL_DETAIL names in the subquery to make a key which you can join to the TOTAL table.
merge into TOTAL t
using ( select d1.code as d1_code
, d2.code as d2_code
, d3.code as d3_code
, d1.name || ' - ' ||
d2.name || ' - ' ||
d3.name as joined_code
from GROUP_LEVEL_DETAIL d1
cross join GROUP_LEVEL_DETAIL d2
cross join GROUP_LEVEL_DETAIL d3
where d1.level_no = 1
and d2.level_no = 2
and d3.level_no = 3
) d
on ( t.gl = d.joined_code )
when matched then
update
set t.gl_code1 = d.d1_code
, t.gl_code2 = d.d2_code
, t.gl_code3 = d.d3_code
The USING subquery generates a result set of all possible permutations of records from GROUP_LEVEL_DETAIL. After your revision I have included a WHERE clause to enforce the implied rule GL = 'level 1 - level 2 - level 3'. You may wish to not do that (perhaps not every record in TOTAL has a valid GL) or extend the WHERE clause to apply any other rules regarding valid combinations.
When the joins are based on primary keys or unique index you should be able to do the following:
--create tables and unix index
create table table1 (code number, field1 number, field2 number, field3 number);
create unique index table1_code_inx on table1 (code);
create table table2 (code number, field1 number, field2 number, field3 number);
create unique index table2_code_inx on table2 (code);
-- update data from table2 to table1
update( select a.FIELD1 A_FIELD1, a.FIELD2 A_FILED2, a.FIELD3 A_FIELD3,
b.FIELD1 B_FIELD1, b.FIELD2 B_FILED2, b.FIELD3 B_FIELD3
from TABLE1 a, TABLE2 b
where a.CODE = b.CODE )
set A_FIELD1 = B_FIELD1,
A_FILED2 = B_FILED2,
A_FIELD3 = B_FIELD3;

How to combine multiple rows, merging cells with different values across columns and rows using SQL

Below is the form of data I have right now from a SQL query:
ID Name Nationality Institution Degree Result
---------------------------------------------
1 Brian USA a b c
1 Brian USA d e f
1 Brian USA h i j
2 Faye UK y z x
2 Faye UK o p q
And the data would ideally be sorted as below:
ID Name Nationality Background
-------------------------------------------------
1 Brian USA a,b,c; d,e,f; h,i,j
2 Faye UK y,z,x; o,p,q
I'm a SQL beginner and I'd very much appreciate any help with this.
Below is my current SQL query:
select
table1.id,
table1.lastname,
table1.firstname,
table1.group,
table2.institution,
table2.degree,
table2.result,
from
table1
inner join
table2 on (table1.id = table2.id)
where
((table1.startyear = '2017')
and (table1.group = 'A'))
You can query as below:
Select Id, [Name], Nationality,
Background = Stuff((Select '; '+Institution+','+Degree+','+Result from #table1 where id = t.Id for xml path('')),1,2,'')
from #table1 t
Group by Id, [Name], Nationality
So using list() and the || string concat in Firebird ( IBExpert ) gives us:
UNTESTED: List() Doc requires 2.1 version or greater.
A prior SO answer using List()
Note Group is on the reserved words list; so you may have to escape it using " in firebird
SELECT table1.id
, table1.lastname
, table1.firstname
, table1."group"
, List(table2.institution ||','||
table2.degree ||','||
table2.result,';') as Background
FROM table1
INNER JOIN table2
ON table1.id = table2.id
WHERE table1.startyear = '2017'
AND table1."group" = 'A'
GROUP BY table1.id
, table1.lastname
, table1.firstname
, table1."group"

trying to concatenate a column into a comma delimited list

i have 3 tables, 1 for products and one for categories the products are assigned to. what IM trying to do is concatenate the column called stCategoryName to a single column in a comma delimited list.
Basically I have the products table containing the primary key for each product and im trying to figure out how to concatenate all the stcategoryName column next to each product so i can have a simplified return
what im trying to get is the following.
stProductID stCategoryName
123 category1,category2,category3
SELECT
dbo.StoreItemTracking.StCategoryID,
dbo.StoreItemTracking.StProductID,
dbo.StoreItemTracking.viewOrder,
dbo.StoreCategories.StCategoryName,
dbo.Store_Products.PartNumber
FROM
dbo.StoreItemTracking
INNER JOIN dbo.StoreCategories
ON dbo.StoreItemTracking.StCategoryID = dbo.StoreCategories.StCategoryID
INNER JOIN dbo.Store_Products
ON dbo.StoreItemTracking.StProductID = dbo.Store_Products.ID
Im stuck as to how to concatenate a column where the query contains 3 tables to select from.
any help greatly appreciated
Look at using coalesce to turn category into a CSV:
See example:
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '')
+ CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT #EmployeeList
You can also use CTE's or Subqueries. See:
http://archive.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=createacommadelimitedlist
Another nice and easy example:
http://www.codeproject.com/Articles/21082/Concatenate-Field-Values-in-One-String-Using-CTE-i
This:
FId FName
--- ----
2 A
4 B
5 C
6 D
8 E
with:
;WITH ABC (FId, FName) AS
(
SELECT 1, CAST('' AS VARCHAR(8000))
UNION ALL
SELECT B.FId + 1, B.FName + A.FName + ', '
FROM (And the above query will return
SELECT Row_Number() OVER (ORDER BY FId) AS RN, FName FROM tblTest) A
INNER JOIN ABC B ON A.RN = B.FId
)
SELECT TOP 1 FName FROM ABC ORDER BY FId DESC
becomes:
FName
----------------------------
A, B, C, D, E,
Don't understand how your products and categories are connected but in general I do like this to create comma separated lists.
SELECT table1.Id
,Csv
FROM table1
CROSS APPLY (
-- Double select so we can have an alias for the csv column
SELECT (SELECT ',' + table2.Name
FROM table2
WHERE table2.Id = table1.Id
FOR XML PATH('')
) AS RawCsv
) AS CA1
CROSS APPLY (
-- Trim the first comma
SELECT RIGHT(RawCsv, LEN(RawCsv) - 1) AS Csv
) AS CA2