SQL Server - CSV values against CSV id - sql-server

I have 2 tables, TableA in which I have ID and Name columns
id name
1 Turret Punch Press
2 Laser Machine
3 Press Brake
4 Other machines
and Table B in which I am passing Id of Table A as CSV value like this
id TableACSV
1 1,2
2 1,3
My query will be something like
Select
id, TableACSV
from tableB
where (--here i am having problem with query--)
The output I want should be like this
id TableACSV
1 Turret Punch Press,Laser Machine
2 Turret Punch Press,Press Brake
I know this might be a bad practice to do .. but currently i need this ..

Using a CSV splitter DelimitedSplit8K
; WITH CTE AS
(
SELECT b.id, a.name
FROM TableB b
CROSS APPLY dbo.DelimitedSplit8K(b.TableACSV, ',') c
INNER JOIN TableA a on c.Item = a.id
)
SELECT DISTINCT c.id, STUFF(d.name, 1, 1, '') AS TableACSV
FROM CTE c
CROSS APPLY
(
SELECT ',' + x.name
FROM CTE x
WHERE x.id = c.id
FOR XML PATH ('')
) d (name)

Related

SQL Server query to select only values not in a list

As an example I have a table in SQL Server :
Id
1
3
5
and I have a list of values 1,2,3
What is the query to select values of my list not in the table.
Expected result :
Id
2
Here are two approaches
Using Not Exists
Select *
from string_split('1,2,3',',') A
Where not exists ( select 1 from YourTable where ID=Value )
Using a LEFT JOIN
Select A.Value
from string_split('1,2,3',',') A
left Join YourTable B on A.value=B.ID
Where B.ID is null
Both Results are
Value
2
SELECT * FROM id_table WHERE id NOT IN (1,2,3);

Displaying nested parent-child relationship

I have a table as below with some data:
ID Name ParentID
-----------------------------
1 A NULL
2 B NULL
3 C 1
4 D 2
5 E 3
As you can see E is a child of C which is a child of A. I am looking for a simple SQL query which can return a string like below given a child ID, for e.g. ID = 5, which is E should have something as below:
Data
-----
A -> C -> E
I have tried below query but stuck on way forward
SELECT a.ID,
a.Name,
COALESCE(b.Name, '->') AS 'ParentName'
FROM MyTable AS a
LEFT JOIN MyTable AS b ON a.ID = b.ID
WHERE a.ID = 5
Any assistance would be appreciated.
Try this:
with cte as(
select * from t where id = 5
union all
select t.id, t.name, t.pid from cte c
join t on c.pid = t.id)
select replace(stuff((select '-' + name from cte
order by id
for xml path('')), 1, 1, ''), '-', '->')
Fiddle http://sqlfiddle.com/#!3/6fdde1/19

Display Distinct data from Join query

Basically I have 2 tables. Lets say A and B.
A has columns like id(PK), pin, name, address
id(PK) pin name address
1 aaa-111-aaa AAA ------
2 bbb-222-bbb BBB ------
3 ccc-333-ccc CCC --------
B has columns like appName, apprequestTime, appAccectTime, id(FK).
appName apprequestTime appAccectTime id(FK).
LLL 2012-4-01 2012-4-01 1
NNN 2012-4-08 2012-5-01 2
QQQ 2012-4-05 2012-4-01 1
MMM 2012-4-02 2012-4-02 2
PPP 2012-5-01 2012-5-01 1
There can be multiple id rows in the B table as it is Foreign Key.
Now, the problem is I am trying to get all the records of one pin of a certain apprequestTime.
I am trying inner join but it shows the pin because of the id in table B.
pin apprequestTime
aaa-111-aaa 2012-4-01
aaa-111-aaa 2012-4-05
bbb-222-bbb 2012-4-08
bbb-222-bbb 2012-4-02
but the result I am expecting should be:
pin apprequestTime
aaa-111-aaa 2012-4-01
2012-4-05
bbb-222-bbb 2012-4-08
2012-4-02
Can any one help:)
In SQL Server 2005+ you can use row_number() for this type of request:
;with cte as
(
select a.pin, b.apprequestTime,
row_number() over(partition by a.pin
order by b.apprequestTime) rn
from tablea a
inner join tableb b
on a.id = b.id
)
select case when rn = 1 then pin else '' end pin,
apprequestTime
from cte;
See SQL Fiddle with Demo
Or without CTE:
select case when rn = 1 then pin else '' end pin,
apprequestTime
from
(
select a.pin, b.apprequestTime,
row_number() over(partition by a.pin
order by b.apprequestTime) rn
from tablea a
inner join tableb b
on a.id = b.id
) t1
See SQL Fiddle with Demo

inner join and group by

I have two tables with identical definition.
T1:
Name VARCHAR(50)
Qty INT
T2:
Name VARCHAR(50)
Qty INT
This is the data each table has:
T1:
Name Qty
a 1
b 2
c 3
d 4
T2:
Name Qty
a 1
b 3
e 5
f 10
I want to have result which can sum the Qty from both the tables based on Name.
Expected resultset:
Name TotalQty
a 2
b 5
c 3
d 4
e 5
f 10
If am do Left Join or Right Join, it is not going to return me the Name from either of the tables.
What i am thinking is to create a temp table and add these records and just do a SUM aggregate on Qty column but i think there should be a better way to do this.
This is how my query looks like which does not return the expected resultset:
SELECT t1.Name, ISNULL(SUM(t1.Qty + t2.Qty),0) TotalQty
FROM t1
LEFT JOIN t2
ON t1.Name = T2.Name
GROUP BY t1.Name
Can someone please tell me if creating a temp table is OK here or there is a better way to do this?
You can use a full outer join:
SELECT
ISNULL(t1.Name, t2.Name) AS Name,
ISNULL(t1.Qty, 0) + ISNULL(t2.Qty, 0) AS TotalQty
FROM t1
FULL JOIN t2 ON t1.Name = T2.Name
See it working online: sqlfiddle
You can use a UNION ALL to select both tables as one, since they have the same definition. From there, you can nest them as a derived table, and then SUM on that:
SELECT [Name], SUM(Qty) AS TotalQty
FROM (
SELECT [Name], Qty
FROM t1
UNION ALL
SELECT [Name], Qty
FROM t2
) YourDerivedTable
GROUP BY [Name]

SQL query to find out some of three fields from three different table

I have three tables, tableA (id, A), tableB (id,B) and tableC (id,C). id is unique and primary key. Now I want to run a query on these three tables to find out sum of values of A,B and C for every id. (i.e. if id 1 is present in tableA but not in tableB then value B should be considered as 0 for id 1).example: tableA:
id A
1 5
2 6
3 2
5 7
tableB:
id B
2 5
3 8
4 1
tableC:
id C
5 2
the output should be:
id Sum
1 (5 + 0 + 0 =)5
2 (6 + 5 + 0 =)11
3 (2 + 8 + 0 =)10
4 (0 + 1 + 0 =)1
5 (7 + 0 + 2 =)9
First get a distinct list ( UNION ) of the IDs so that you include all, then LEFT JOIN to add the values together.
Something like
SELECT IDs.ID,
IFNULL(tableA.A,0) + IFNULL(tableB.B,0) + IFNULL(tableC.C,0) SumVal
FROM (
SELECT ID
FROM tableA
UNION
SELECT ID
FROM tableB
UNION
SELECT ID
FROM tableC
) IDs LEFT JOIN
tableA ON IDs.ID = tableA.ID LEFT JOIN
tableB ON IDs.ID = tableB.ID LEFT JOIN
tableC ON IDs.ID = tableC.ID
Something like this should work:
select id, sum(val) from
( select id, "A" as val from "tableA"
union all
select id, "B" as val from "tableB"
union all
select id, "C" as val from "tableC" ) as joined
group by id
order by id
I could not test it with MySql but this works my databases (HSQLDB, Oracle):
select ID, sum(X) from
(SELECT ID, A as X FROM tableA
UNION
SELECT ID, B as X FROM tableB
UNION
SELECT ID, C as X FROM tableC)
group by ID
Not sure about the exact MySQL syntax, but this works in SQL Server:
SELECT ID, SUM(ColToSum) As SumValue FROM
(
SELECT ID, A As ColToSum FROM TableA
UNION ALL
SELECT ID, B As ColToSum FROM TableB
UNION ALL
SELECT ID, C As ColToSum FROM TableC
) Combined
GROUP BY ID
Remember to use "UNION ALL", not just "UNION" which strips out duplicate rows as it combines (see http://dev.mysql.com/doc/refman/5.0/en/union.html)

Resources