How to update the column using two tables based on conditions? - sql

I have two tables such as STR_IndentHeader and STR_IndentDetail.
STR_IndentDetail:
IndentID ItemID ItemStatusID
-------- ------ ------------
1 22 4
1 23 4
2 11 4
2 12 3
2 13 3
STR_IndentHeader:
IndentID StatusID
-------- -----------
1 1
2 1
Here I want to Update the STR_IndentHeader StatusID = 4, When all the STR_IndentDetail.ItemID's ItemStatusID = 4 with respect to IndentID. Else I want to Update the STR_IndentHeader.StatusID = 3.
In the above tables, In STR_IndentDetail, For IndentID "1", all the ItemStatusID of the Items is 4. So we have Update STR_IndentHeader.StatusID = 4.
But for IndentID "2", One Item's(ie. ItemID=11) ItemStatusID = 4 and the Remaining two items ItemStatusID = 3. So In this case, we have to update STR_IndentHeader.StatusID = 3.
I hope it would give better idea. How to do this?
My Desired Result for the above tables would be like this:
STR_IndentHeader:
IndentID StatusID
-------- -----------
1 4
2 3

Based off the information provided I am assuming that you want the statusID in STR_IndentHeader to be the smallest ItemStatusID value from STR_IndentDetail for that IndentID.
If this is the case please try the below:
update STR_IndentHeader
set statusid = minitemstatusid
from
(select indentid,MIN(itemstatusid) as minitemstatusid
from STR_IndentDetail
group by indentid) id
where id.IndentID = STR_IndentHeader.indentid
EDIT:
Based off comments if you want to statically apply an ItemStatusID of 3 if the statusID is not 4 then:
update STR_IndentHeader
set statusid = case minitemstatusid when 4 then 4 else 3 end
from
(select indentid,MIN(itemstatusid) as minitemstatusid
from STR_IndentDetail
group by indentid) id
where id.IndentID = STR_IndentHeader.indentid

Here is one way you can do this using CROSS APPLY available in SQL Server 2005. Hope that helps.
UPDATE SH
SET SH.StatusID = (CASE WHEN DC.DistinctCount = 1 THEN 4 ELSE 3 END)
FROM dbo.STR_IndentHeader SH
CROSS APPLY (
SELECT SD.IndentID
, COUNT(DISTINCT ItemStatusID) AS DistinctCount
FROM dbo.STR_IndentDetail SD
WHERE SH.IndentID = SD.IndentID
GROUP BY SD.IndentID
) DC

This worked for me when I tested it setting up a database with your sample data:
UPDATE STR_IndentHeader ih
SET StatusID = (SELECT MIN(ItemStatusID) FROM STR_IndentDetail id WHERE id.IndentID = ih.IndentID)
WHERE IndentID IN (SELECT DISTINCT IndentID FROM PUR_POIndent WHERE POID = 8)

Related

SQL concat function, combine size and colour

If there is a table called variant
id slug slug_id
------- --------- ----------
1 s 10
1 m 10
1 l 10
1 black 11
1 pink 11
1 ship_us 12
1 ship_uk 12
2 xl 10
2 xxl 10
2 blue 11
2 white 11
Result I need in this format:
id variant_slug
-------- ------------
1 1-s-black-ship_us
1 1-s-black-ship_uk
1 1-s-pink-ship_us
1 1-s-pink-ship_uk
1 1-m-black-ship_us
1 1-m-black-ship_uk
1 1-m-pink-ship_us
1 1-m-pink-ship_uk
1 1-l-black-ship_us
1 1-l-black-ship_uk
1 1-l-pink-ship_us
1 1-l-pink-ship_uk
2 2-xl-blue
2 2-xl-white
2 2-xxl-blue
2 2-xxl-white
Q: this record is in same variant table. I have almost no experience using UDFs, stored procedures, I need to be done this thing through query. Is this possible without using UDFs, SP's.
Perhaps a self-join assuming the length of size<=3.
Select A.ID
,variant_slug = concat(A.id,'-',A.slug,'-',B.slug)
from YourTable A
Join YourTable B
on A.ID=B.ID
and A.slug<>B.slug
and len(B.slug)>3
and len(A.slug)<=3
Results
ID variant_slug
1 1-l-black
1 1-l-pink
1 1-m-black
1 1-m-pink
1 1-s-black
1 1-s-pink
2 2-xl-blue
2 2-xl-white
2 2-xxl-blue
2 2-xxl-white
Rather than len(), you can enumerate the sizes i.e. {NOT } IN ('s','m','l','xl','xxl')
Select A.ID
,variant_slug = concat(A.id,'-',A.slug,'-',B.slug)
from YourTable A
Join YourTable B
on A.ID=B.ID
and A.slug<>B.slug
and B.slug NOT IN ('s','m','l','xl','xxl')
and A.slug IN ('s','m','l','xl','xxl')
You can go for INNER JOIN by separating the table into two separate tables: size, color and get the variant data, as given below:
declare #slug table(id int, slug varchar(100))
insert into #slug values
(1,'s')
,(1,'m')
,(1,'l')
,(1,'black')
,(1,'pink')
,(2,'xl')
,(2,'xxl')
,(2,'blue')
,(2,'white');
SELECT size.id, CONCAT_WS('-',size.id,size.size, color.color) as variant_size
from (select id,slug as size from #slug where slug in ('s','m','l','xl','xxl') ) as size
INNER JOIN (select id,slug as color from #slug where slug NOT in ('s','m','l','xl','xxl') ) as COLOR
on color.id = size.id
id
variant_size
1
1-s-black
1
1-s-pink
1
1-m-black
1
1-m-pink
1
1-l-black
1
1-l-pink
2
2-xl-blue
2
2-xl-white
2
2-xxl-blue
2
2-xxl-white

Left Join Display All Data From Table1 and Table2

I am trying to do a left join so that I get all of my rows from Table 1 even if there is no value corresponding to it in the second table.
My structures are:
Location Table:
ID LocName
1 Trk1
2 Trk2
3 Trk3
4 Unk
Quantity Table:
ID PartID Quantity LocationID
1 1 2 1
2 3 12 2
3 2 6 1
4 6 8 3
5 6 5 1
I am trying to join but also make a query on a specific PartID. My query is:
SELECT
INV_LOCATIONS.ID AS LocationID,
INV_LOCATIONS.NAME AS LocationName,
INV_QUANTITY.QUANTITY AS Quantity
FROM INV_LOCATIONS
LEFT JOIN INV_QUANTITY ON INV_LOCATIONS.ID = INV_QUANTITY.LOCATION_ID
WHERE INV_QUANTITY.PART_ID = 1;
My output right now would be:
ID LocName Quantity
1 Trk1 5
3 Trk3 8
The Desired output is:
ID LocName Quantity
1 Trk1 5
2 Trk2 NULL/0
3 Trk3 8
4 Unk NULL/0
I assume it is because I have the WHERE INV_QUANTITY.PART_ID = 1 and that is forcing it to be in the quantity table. I need to be able to verify it is on the right part but how do I also include it if it doesn't exist. I know I have done something very similar before but I cannot remember which project and so I cannot find the code anywhere.
You need to move the filtering logic to the ON clause:
SELECT il.ID AS LocationID, il.NAME AS LocationName,
iq.QUANTITY AS Quantity
FROM INV_LOCATIONS il LEFT JOIN
INV_QUANTITY iq
ON il.ID = iq.LOCATION_ID AND iq.PART_ID = 1;

How to compare each group of one table with a column in another table?

I have two tables:
TypeTable
TypeId PersonClassificationId
----------------------
1 1
1 2
1 3
2 1
2 2
PersonClassificationTable
PersonClassificationId Capacity
----------------------
1 2
2 2
3 2
I need to select such TypeId that in the entire TypeTable table do not have at least one PersonClassificationID specified in PersonTable.
So, if PersonTable has 1, 2, 3, then TypeId = 2 should be selected, because there is no record in TypeTable:
TypeId PersonClassificationId
----------------------
2 3
How can I do that?
It is undesirable to use cursors : )
I think that you can do what you want by generating all possible combinations of types and classifications, and then filter on those that do not exist in the mapping table:
select t.TypeId, pc.PersonClassificationId
from (select distinct TypeId from TypeTable) t
cross join PersonClassificationTable p
where not exists (
select 1
from TypeTable t1
where t1.TypeId = t.TypeId and t1.PersonClassificationId = p.PersonClassificationId
)

SQL Query - Convert data values into attributes into antother table.

I am building a report and I am stuck formulating a query. I am bringing the following data from multiple tables after a lot of joins.
ID TYPE RATING
----- ---- ------
ID_R1 A 1
ID_R1 B 3
ID_R2 A 2
ID_R2 B 1
ID_R3 A 4
ID_R3 B 4
ID_R4 A 2
ID_R4 B 3
ID_R5 A 2
ID_R5 B 3
What actually is happening is that Every ID will have a Rating for Type A & B so what I need to do is transform the above into the following
ID Type_A_Rating Type_B_Rating
----- ------------- -------------
ID_R1 1 3
ID_R2 3 1
ID_R3 4 4
ID_R4 2 3
ID_R5 2 3
I have think group by and different techniques but so far I am unable to come up with a solution. Need help F1! F1!
p.s just for the record my end game is getting the count of (A,B) combinations
Type_A_Rating Type_B_Rating Count
------------- ------------- -----
1 1 0
1 2 0
1 3 1
1 4 0
2 1 0
2 2 0
2 3 2
2 4 0
3 1 1
3 2 0
3 3 0
3 4 0
4 1 0
4 2 0
4 3 0
4 4 1
From this you can see that a simple GROUP BY with any form AND OR conditions doesn't suffice until I get the data as mentioned. I could use two intermediate/temp tables, in one get Type_A_Rating with ID and then in second Type_B_Rating with ID and then in another combine both but isn't there a better way.
This should work as SQL engine agnostic solution (provided that there is exactly one row with type A for each ID and one row with type B for each ID):
select
TA.ID,
TA.RATING as Type_A_Rating,
TB.RATING as Type_B_Rating
from
(select ID, RATING
from T where TYPE = 'A') as TA
inner join
(select ID, RATING
from T where TYPE = 'B') as TB
on TA.ID = TB.ID
Related SQL Fiddle: http://sqlfiddle.com/#!9/7e6fd9/2
Alternative (simpler) solution:
select
ID,
sum(case when TYPE = 'A' then RATING else 0 end) as Type_A_Rating,
sum(case when TYPE = 'B' then RATING else 0 end) as Type_B_Rating
from
T
group by
ID
Fiddle: http://sqlfiddle.com/#!9/7e6fd9/3
EDIT:
The above is correct but both can be simplified a bit:
select TA.ID, TA.RATING as Type_A_Rating, TB.RATING as Type_B_Rating
from T TA join
T TB
on TA.ID = TB.ID AND A.type = 'A' and B.type = 'B';
And (because I prefer NULL when there are no matches:
select ID,
max(case when TYPE = 'A' then RATING end) as Type_A_Rating,
max(case when TYPE = 'B' then RATING end) as Type_B_Rating
from T
group by ID

sqlquery to get missing

I have a table student with following columns
StudentId SemesterId ExamYearId
1 1 1
1 2 2
1 3 3
3 1 1
3 2 2
3 3 4
7 1 1
7 3 4
8 1 1
8 2 2
I want a query to get all such student for whom no data exists for semesterid=3 and examyearid=3, however same student should have data for semesterid=2.
In this case it should return me studentid=8 as studentid=8 has data for semesterid=2 and examyearid=2 however no data for examyearid=3 and semesterid=3.
Basically I want to be able to input semesterid and examyearid and find which studentids have not filled data for that semesterid and examyearid.
DECLARE #SemesterId INT
,#ExamYearId INT
SET #SemesterId = 3;
SET #ExamYearId = 3;
SELECT *
FROM TableName t
WHERE EXISTS (SELECT 1
FROM TableName
WHERE SemesterId = #SemesterId - 1
AND ExamYearId = #ExamYearId - 1
AND t.StudentId = StudentId )
AND NOT EXISTS (SELECT 1
FROM TableName
WHERE SemesterId = #SemesterId
AND ExamYearId = #ExamYearId
AND t.StudentId = StudentId )
SELECT st1.*
FROM Student st1
left join Student st2
on st1.id = st2.id
and st1.Semesterid=2
and st2.Semesterid=3
and st2.Examyearid=3
where st2.id is null