SQL multiple results on one row when only one column has different values - sql

I currently have a similar query to this one..
select i.App_Id as ApplicationId,
Cast(i.ObjectId as NVARCHAR(50)) as ObjectId,
1 as ActivityId,
Cast(case
when oh.ObjectId is null then 0
else 1
end as BIT) as Highlight,
iu.UserId as UserId
from table0 i
inner join table1 iu
on i.IdeaID = iu.IdeaID
left join table2 oh
on oh.ObjectId = i.IdeaID
left join table3 mIS
on i.IdeaID = mIS.IdeaID
AND mIS.EndTime is null
inner join table4 mISF
on mISF.StateFluxId = mIS.StateFluxId
where (iu.RelationId = 1 or iu.RelationId = 2)
which is returning, for example:
2 | 1 | 1 | 1 | 1
2 | 1 | 1 | 1 | 2
2 | 1 | 1 | 1 | 3
I'm trying to change it in order to merge the results of the 5th column when the other column values are the same:
2 | 1 | 1 | 1 | 1,2,3
Is this possible? Didn't manage to accomplish it using the Stuff function..
Thanks!

Have you tried like this,
SELECT DISTINCT i.App_Id AS ApplicationId
,Cast(i.ObjectId AS NVARCHAR(50)) AS ObjectId
,1 AS ActivityId
,Cast(CASE
WHEN oh.ObjectId IS NULL
THEN 0
ELSE 1
END AS BIT) AS Highlight
,
--iu.UserId as UserId
(stuff(SELECT ',' + userid FROM table1 WHERE Ideaid = iu.IdeaId FOR XML path(''), 1, 1, '')) AS UserId
FROM table0 i
INNER JOIN table1 iu ON i.IdeaID = iu.IdeaID
LEFT JOIN table2 oh ON oh.ObjectId = i.IdeaID
LEFT JOIN table3 mIS ON i.IdeaID = mIS.IdeaID
AND mIS.EndTime IS NULL
INNER JOIN table4 mISF ON mISF.StateFluxId = mIS.StateFluxId
WHERE (
iu.RelationId = 1
OR iu.RelationId = 2
)

Based on your code I have added the XML PATH () .Please do necessary changes according to your requirement
select i.App_Id as ApplicationId,
Cast(i.ObjectId as NVARCHAR(50)) as ObjectId,
1 as ActivityId,
Cast(case
when oh.ObjectId is null then 0
else 1
end as BIT) as Highlight,
stuff(
(
SELECT ',' + CAST(IU.USERID AS VARCHAR(10))
FROM table1 t2 WHERE iu.IdeaID = t2.IdeaID
FOR XML PATH('')
)
,1,1,'') AS USERID
from table0 i
inner join table1 iu
on i.IdeaID = iu.IdeaID
left join table2 oh
on oh.ObjectId = i.IdeaID
left join table3 mIS
on i.IdeaID = mIS.IdeaID
AND mIS.EndTime is null
inner join table4 mISF
on mISF.StateFluxId = mIS.StateFluxId
where (iu.RelationId = 1 or iu.RelationId = 2)
GROUP BY i.App_Id
,i.ObjectId,
oh.ObjectId

Related

How to return 1 row instead of 3 when one column has different data

I have 3 rows of data returned from a query
OrderId | OtherId
--------+---------
1234 | 444
1234 | 555
1234 | 666
How to return data in this format
OrderId | OtherId | OtherId2 | OtherId
--------+---------+----------+--------
1234 | 444 | 555 | 666
Can I use Distinct for this problem?
EDIT
The result set comes from a query such as
left join (
Select distinct
o.id
,OL2.db
,case
when i.cust = 'cust2' then
case
when
lower(pdf.dept) not like 'abc%' or pdf.dept is null
then 'Yes'
else'No'
end
else 'Yes'
end as 'Show'
,otherId
from order o with(nolock)
Join instance i with(nolock) on i.id = o.id
Join orderLine ol with(nolock) on ol.id = o.SocialNetworker_Order_InstanceId
and ol.id = o.id
join product p with(nolock) on o.id = p.id
and ol.id = p.id
left join productEx pdf with(nolock) on p.id = pdf.id
and o.id = pdf.id
Where i.cust in ('cust1')
) ol2 on OL2.id = sno.id
and OL2.id2 = sno.id2
and i.db = cc.db
How to work solution into the above code?
You can use row_number() and conditional aggregation:
select orderid,
max(case when seqnum = 1 then otherid end) as otherid_1,
max(case when seqnum = 2 then otherid end) as otherid_2,
max(case when seqnum = 3 then otherid end) as otherid_3
from (select t.*, row_number() over (partition by orderid order by otherid) as seqnum
from t
) t
group by orderid;
Use an outer join with cascading join conditions:
select t1.OrderId, t1.OtherId OtherId1, t2.OtherId OtherId2, t3.OtherId OtherId3
from orders t1
left join orders t2 on t2.OrderId = t1.OrderId
and t2.OtherId > t1.OtherId
left join orders t3 on t3.OrderId = t2.OrderId
and t3.OtherId > t2.OtherId
If there are less than 3 other ids, the right-most columns will be null.
This query will work on pretty much any database.

Create table with values from one column and another column without intersection

I have a table like so:
userid | clothesid
-------|-----------
1 | 1
1 | 3
2 | 1
2 | 4
2 | 5
What I want from this table is a table like so:
userid | clothesid
-------|-----------
1 | 4
1 | 5
2 | 3
How can I do this?
I've tried it with one entry as:
select distinct r.clothesid from table r where r.clothes not in (select r1.clothes from table r1 where r1.userid=1);
and this returns 4,5, but I'm not sure where to proceed from here
You can cross join the list of userids and the list of clothesid to generate all combinations, and then use not exists on the original table to identify the missing rows:
select u.userid, c.clothesid
from (select distinct userid from mytable) u
cross join (select distinct clothesid from mytable) c
where not exists(
select 1 from mytable t on t.userid = u.userid and t.clothesid = c.clothesid
)
I think you want:
select (case when t1.clothesid is not null then 2 else 1 end),
coalesce(t1.clothesid, t2.clothesid)
from (select t.*
from t
where t.userid = 1
) t1 full join
(select t.*
from t
where t.userid = 2
) t2
on t1.clothesid = t2.clothesid
where t1.clothesid is null or t2.clothesid is null;
Actually, I think I have a simpler solution:
select (case when min(t.userid) = 1 then 2 else 1 end), clothesid
from t
group by clothesid
having count(*) = 1;
Here is a db<>fiddle.
Left join all the combinations of userid and clothesid to the table and return only the unmatched rows:
select t1.userid, t2.clothesid
from (select distinct userid from tablename) t1
cross join (select distinct clothesid from tablename) t2
left join tablename t on t.userid = t1.userid and t.clothesid = t2.clothesid
where t.userid is null
Or with the operator EXCEPT:
select t1.userid, t2.clothesid
from (select distinct userid from tablename) t1
cross join (select distinct clothesid from tablename) t2
except
select userid, clothesid
from tablename
See the demo.
Results:
> userid | clothesid
> -----: | --------:
> 1 | 4
> 1 | 5
> 2 | 3

Update data where ID match and use case to choose what data

I have two tables
T1:
ID, Truck, Trailer
1 null null
2 null null
T2:
ID, Type, ResourceID
1 R 111
1 F 222
1 D 333
2 R 444
2 F 555
I need a result where
ID, Truck, Trailer
1 111 222
2 444 555
How can I update T1.Truck = T2.ResourceID when T2.Type = R and T1.Trailer = T2.ResourceID when T2.Type = F where T1.ID = T2.ID.
This is what I have so far
UPDATE T1
SET T1.Truck = CASE
WHEN T2.Type = 'R' THEN T2.ResourceId
ELSE T1.Truck
END,
T1.Trailer = CASE
WHEN T2.Type = 'F' THEN T2.ResourceId
ELSE T1.Trailer
END
FROM T1 INNER JOIN (SELECT Id, Type, ResourceId
FROM T2) T2
ON T1.Id = T2.Id
This will only Truck, but not trailer.
What am I missing?
The problem with your current update query is that the update will update one column to null as it can't match both conditions at the same time.
If you did a select * instead of the update the result would look like:
ID Truck Trailer Id Type ResourceId
1 NULL NULL 1 R 111 -- this will set R = 111 and F = null
1 NULL NULL 1 F 222 -- this will set F = 222 and R = null
1 NULL NULL 1 D 333 -- this will set R = null and F = null
2 NULL NULL 2 R 444 -- this will set R = 444 and F = null
2 NULL NULL 2 F 555 -- this will set R = null and F = 555
Here you can see that when Type matches R the update for F will update to null et cetera.
One solution is to join the T2 table twice:
UPDATE T1
SET
T1.Truck = T2.ResourceId
,
T1.Trailer = T3.ResourceId
FROM T1
INNER JOIN (SELECT Id, ResourceId FROM T2 WHERE Type = 'R') T2 ON T1.Id = T2.Id
INNER JOIN (SELECT Id, ResourceId FROM T2 WHERE Type = 'F') T3 ON T1.Id = T3.Id
If there might not always be both types (R,F) then use left join instead of inner join and check for null values.
Edit: thinking a bit more gives this query:
UPDATE T1
SET
T1.Truck = ISNULL(T.rValue, T1.Truck),
T1.Trailer = ISNULL(T.fValue, T1.Trailer)
FROM T1
INNER JOIN (
SELECT
Id,
rValue = MAX(CASE WHEN Type = 'R' THEN ResourceId END),
fValue = MAX(CASE WHEN Type = 'F' THEN ResourceId END)
FROM T2 GROUP BY id
) T ON T1.Id = T.Id
On a side note: using an alias for a derived table that is also a table name can be pretty confusing and should be avoided.
you can PIVOT the table t2 before updating the t1 table
Use the following query to pivot the t2 table.
SELECT ID, R, F
FROM t2
PIVOT (Max(resourceID)
FOR type IN ([R],[F]))pv
Now the result will in the format of t1 table you can easily update using the following query
UPDATE A
SET Trailer = F,
Truck = R
FROM t1 A
INNER JOIN (SELECT ID, R, F
FROM t2
PIVOT (Max(resourceID)
FOR type IN ([R],
[F]))pv) B
ON A.ID = b.ID
SQLFIDDLE DEMO
You can use a JOIN with a condition for each case, so you would JOIN to T2 twice. First on the Id and [Type] = 'R' and again, with [Type] = 'F'.
Here's some runnable sample code:
CREATE TABLE #t1 (id INT, Truck INT, Trailer int)
CREATE TABLE #t2 (id INT, [Type] VARCHAR(1), ResourceId int)
INSERT INTO #t1
( id, Truck, Trailer )
VALUES (1, NULL, NULL),
(2, NULL, NULL)
INSERT INTO #t2
( id, [Type], ResourceId )
VALUES ( 1, 'R', 111),
( 1, 'F', 222),
( 1, 'D', 333),
( 2, 'R', 444),
( 2, 'F', 555)
UPDATE #t1
SET Truck = TR.ResourceId, Trailer = TF.ResourceId
FROM #t1
INNER JOIN #t2 AS TR ON TR.id = #t1.id AND TR.[Type] = 'R'
INNER JOIN #t2 AS TF ON TF.id = #t1.id AND TF.[Type] = 'F'
SELECT * FROM #t1
DROP TABLE #t1
DROP TABLE #t2

how can I swap two records in sql server with script

I want swap two records in sql server for example
How can i do it?
You can do it in one statement with JOIN like this
UPDATE t1
SET t1.id = t2.id
FROM table1 t1 JOIN table1 t2
ON (t1.id = 1 AND t2.id = 2)
OR (t1.id = 2 AND t2.id = 1)
Output after update:
| ID | NAME | FAMILY |
|----|------|--------|
| 1 | Mary | Simson |
| 2 | Jame | Ander |
Here is SQLFiddle demo
SELECT
*,CASE WHEN id=123 then 987 ELSE 123 END AS JoinId
INTO #Temp
FROM YourTable
WHERE ID in (123,987)
--swap values
UPDATE y
SET col1=t.col1
,col2=t.col2
FROM YourTable y
INNER JOIN #Temp t ON y.id =t.JoinId
WHERE ID in (123,987)
in the case that ID is identity you could use a combined solution between #Vaibs_Cool and #user814064
something like this
DECLARE #aID INT, #bID INT
SELECT #aID = 123, #bID = 987
;WITH ToSwap AS
(
SELECT CASE WHEN id = #aID THEN #bID ELSE #aID END AS id, [Name], [Family]
FROM YourTable
WHERE id IN (#aID, #bID)
)
UPDATE YourTable
SET [Name]=ToSwap.[Name], [Family] = ToSwap.[Family]
FROM YourTable
INNER JOIN ToSwap ON YourTable.id =ToSwap.Id

dynamic operations with 2 tables and 1 insert SQL Server

I have 2 tables:
table1
id someval someatt
-------------------
1 23 name1
2 56 name2
3 76 name3
4 456 name4
5 53 name5
6 67 name6
7 12 name7
8 43 name8
9 99 name9
10 567 name10
table2
id someval someatt
-------------------
1 23.3 name1
2 5.6 name2
3 8.76 name3
4 4.56 name4
5 5.3 name5
6 6.7 name6
7 1.2 name7
8 4.3 name8
9 9.9 name9
10 56.7 name10
I need to insert to a new table some operations of various fields of both tables so, for example
iteration1
x = get value from table1 where id 1
y = get value from table1 where id 2
a = get value from table2 where id 1
b = get value from table2 where id 2
iteration2
r = get value from table1 where id 2
s = get value from table1 where id 3
u = get value from table2 where id 2
v = get value from table2 where id 3
iterationn.
q = get value from table1 where id n-1
p = get value from table1 where id n
o = get value from table2 where id n-1
e = get value from table2 where id n
Then insert into NEWTABLE
(a*b + x+y), (r*s + u*v) ...(q*p+o*e)
sO I was thinking (IF I have to do this 100 times):
SET #counter = 1;
SET #template = '';
SET #N = 100;
WHILE(#counter < #N)
Select #x = value from table 1 where id = #counter
Select #y = value from table 1 where id = #counter + 1
Select #a = value from table 2 where id = #counter
Select #b = value from table 2 where id = #counter + 1
#template = #template + ' (#x*#y + #a*#b), '
end
so at the end of the loop I have a full template
and then EXEC(#template) ,
How could you optimize this?
How to do something like I described?
(table1 and table2 are samll examples of my tables)
Is there a way The 4 select
statements are avoided?
output table:
result1 result2 result3 .... result100
---------------------------------------
float float float ... float
where float is a result of calculating (a*b + x+y) for each value in table1 and table2
This will work with SQL 2005 & up, using the same data you listed.
SELECT t1x.id AS smaller_id,
( t1x.someval * t1y.someval ) + ( t2a.someval * t2b.someval ) AS result
FROM dbo.table1 AS t1x
INNER JOIN dbo.table1 AS t1y ON t1x.id + 1 = t1y.id
INNER JOIN dbo.table2 AS t2a ON t2a.id = t1x.id
INNER JOIN dbo.table2 AS t2b ON t2b.id = t1y.id
If you want it horizontal, you'll have to PIVOT the results.
SELECT 'Calculation Result' AS CalcRes,
[result1], [result2], [result3], [result4], [result5], [result6], [result7], [result8], [result9]
FROM (
SELECT 'result' + cast(t1x.id AS varchar(4)) AS result_name,
( t1x.someval * t1y.someval ) + ( t2a.someval * t2b.someval ) AS result
FROM dbo.table1 AS t1x
INNER JOIN dbo.table1 AS t1y ON t1x.id + 1 = t1y.id
INNER JOIN dbo.table2 AS t2a ON t2a.id = t1x.id
INNER JOIN dbo.table2 AS t2b ON t2b.id = t1y.id
) AS Results
PIVOT (
min( result ) --there needs to be an aggregate function here
FOR result_name IN ([result1], [result2], [result3], [result4], [result5], [result6], [result7], [result8], [result9])
) AS PivotedResults
You'll need to use dynamic SQL for this, because you need to know the names of your result colums before you pivot.
Join all the records together:
insert
NEWTABLE (theid, newval)
select
t1_p.id as theid
(t2_p.someval * t2_n.someval) + (t1_p.someval * t1_n.someval) as newval
from
Table1 t1_p
inner join
Table1 t1_n on t1_p.id + 1 = t1_n.id
inner join
Table2 t2_p on t1_p.id = t2_p.id
inner join
Table2 t2_n on t1_n.id = t2_n.id
Not sure I understand your question fully but....
;with cte1 as
(
select
T1_1.id,
T1_1.someval as x,
T1_2.someval as y
from #T1 as T1_1
inner join #T1 as T1_2
on T1_1.id = T1_2.id-1
),
cte2 as
(
select
T2_1.id,
T2_1.someval as a,
T2_2.someval as b
from #T2 as T2_1
inner join #T2 as T2_2
on T2_1.id = T2_2.id-1
)
select (a*b + x*y)
from cte1 as T1
inner join cte2 as T2
on T1.id = T2.id
Might you try something like
INSERT INTO SomeTable
SELECT
(x.value * y.value) + (a.value * b.value)
FROM
Table1 x
Table1 y on y.id = x.id + 1
Table2 a on a.id = x.id
Table2 b on b.id = x.id + 1
WHERE
x.Id = #counter