Get the records which don't match the condition - sql

I have three tables that have data like this:
Table CON_MEMBER:
CONTAINER_DATA_BO
CONTAINER_NUMBER_BO
PARENT_REF_001
CHILD_REF_001
PARENT_REF_001
CHILD_REF_002
Table CON_DATA:
HANDLE
CONTAINER_NUMBER
CHILD_REF_001
CHILD_001
CHILD_REF_002
CHILD_002
Table CON_CUSTOM_DATA:
CONTAINER_DATA_BO
DATA_FIELD
DATA_ATTR
CHILD_REF_001
QTY
10
CHILD_REF_001
CLASS
CLASS 1
CHILD_REF_001
MAT
MAT 1
CHILD_REF_001
TYPE
BARREL
CHILD_REF_001
TRANSPORT
1
CHILD_REF_002
QTY
100
CHILD_REF_002
CLASS
CLASS 2
CHILD_REF_002
MAT
MAT 2
CHILD_REF_002
TYPE
DRUM
Now I have written a query that will get all the child container numbers against the parent container for which the CON_CUSTOM_DATA.TRANSPORT is not 1
SELECT DISTINCT
cd.CONTAINER_NUMBER
FROM
CON_MEMBER cm1
INNER JOIN
CON_MEMBER cm2 ON cm1.CONTAINER_NUMBER_BO = cm2.CONTAINER_DATA_BO
INNER JOIN
CON_DATA cd ON cd.HANDLE = cm1.CONTAINER_NUMBER_BO
LEFT JOIN
CON_CUSTOM_DATA ccd ON cd.HANDLE = ccd.CONTAINER_DATA_BO
WHERE
cm1.CONTAINER_DATA_BO = 'PARENT_REF_001'
AND ccd.DATA_ATTR <> '1'
But the query returns both the child "CHILD_002" as well as "CHILD_001". What is am expecting from above query is to get the Child Container Number "CHILD_002", Since for this container TRANSPORT is not 1.
Please help me achieve this output.
Thanking you in advance.

You could try something like this
SELECT DISTINCT cd.CONTAINER_NUMBER
FROM CON_MEMBER cm
JOIN CON_DATA cd ON cm.CONTAINER_NUMBER_BO=cd.HANDLE
WHERE NOT EXISTS (SELECT 1
FROM CON_CUSTOM_DATA ccd
WHERE cd.HANDLE = ccd.CONTAINER_DATA_BO
AND ccd.DATA_FIELD='TRANSPORT'
AND ccd.DATA_ATTR=1);

Related

SQL join query to fetch the data items based on max dDateEffective and other conditions

I'm trying to result based on joining these 4 tables,
Table: DataItem
iDataItemID iDataTypeID iEmployeeID
275599 8 1
Table: DataItemStatus
i
iDataStatusID iDataItemID iDataItemStatusID (Foreign key from RefDataItemStatus) dDateEffective
1 275599 1 22/07/2018
2 275599 4 21/07/2018
3 275599 1 20/07/2018
Table: RefDataItemStatus
iDataItemStatusID sDataItemStatus
5 Terminal
4 Failed
3 Processed
2 Processing
1 Submitted
Table: RefDataType
iDataTypeID sDataType
8 EmployeeAgreement
I need to fetch the data items on a particular dataItemStatusID and iDataTypeID.
I'm able to achieve this by the following query,
DECLARE #DataItemCurrentStatusID INT = 1
DECLARE #DataTypeID INT = 8
Select DataItem.iDataItemID,
DataItem.iDataTypeID,
DataItemStatus.iDataItemCurrentStatusID,
DataItemStatus.iDataItemStatusID
from DataItem
INNER JOIN DataItemStatus ON
DataItemStatus.iDataItemID =
DataItem.iDataItemID
INNER JOIN ORefDataItemStatus ON
DataItemStatus.iDataItemStatusID =
RefDataItemStatus.iDataItemStatusID
AND DataItemStatus.iDataItemCurrentStatusID = #DataItemCurrentStatusID AND
DataItem.iDataTypeID = #DataTypeID
The issue is there could multiple data items mapped with the same status in DataItemStatus table. I need to fetch the dataItem, only if the dDateEffective value is max in DataItemStatus table for that dataItem.
Like in the below example as in the snapshot,
If i want to fetch the dataItems in failed state (i.e iDataTypeID = 4), I dont want to get the iDataItemID = 275599 in the result, bcoz there is an update to that iDataItemID with a new status again on 22/07/2018
enter image description here
I got it resolved,
Select DI.iDataItemID,
DI.iDataTypeID,
DIS.iDataItemCurrentStatusID,
DIS.iDataItemStatusID
from DataItem DI
INNER JOIN DataItemStatus DIS ON DIS.iDataItemID = DI.iDataItemID
INNER JOIN RefDataItemStatus ON DIS.iDataItemCurrentStatusID =
RefDataItemStatus.iDataItemStatusID
AND DIS.iDataItemCurrentStatusID = 1 AND DI.iDataTypeID = 8 and DIS.dDateEffective IN
(
SELECT Max(dDateEffective) FROM OT_BackendUpdate_DataItemStatus Where
OT_BackendUpdate_DataItemStatus.iDataItemID = DI.iDataItemID
)

Combining SQL Tables for one source of information

I'm trying to combine 3 different tables into one single row in a query but having some problems. Currently I have four tables; PaintSched, Painted_Log, Paint_Defect, and Paint_Inspection.
PaintSched - Single entry, when scheduler just schedules some parts to be painted
LOT QTY
1 150
2 100
Painted_Log - The paint department then takes the lot and says how many they were able to paint
LOT(FK) QTYPainted
1 145
2 100
Paint_Defect - Master List of defects for paint inspection after parts have been painted. We hand inspect all of our parts that we paint for quality.
DID Defect
1 Scratch
2 Paint Run
Paint_Inspection - Everytime a defect is found the inspector hits a correlating button and the following gets logged. Lot is FK and DID stands for Defect ID from Paint_Defect. QTY is always 1
Lot(FK) DID(FK) QTY
1 1 1
1 1 1
1 2 1
1 1 1
2 2 1
1 2 1
2 1 1
What I'm trying to get is the following output:
Lot Sched Painted Scratch Paint Run
1 150 145 3 2
2 100 100 1 1
I've tried the following to no avail:
SELECT PaintSched.Scheduled, PaintSched.Lot, PaintSched.qty, PaintSched.Is_Painted, Painted_Log.falloff
FROM PaintSched
INNER JOIN Painted_Log ON PaintSched.Lot = Painted_Log.lot
INNER JOIN MPA_Desc ON MPA_Desc.MPAID = PaintSched.MPAID
inner JOIN (
SELECT lot, sum(Paint_Inspection.qty) as seds
FROM Paint_Inspection
WHERE Paint_Inspection.Status = '1'
) AS seeds ON PaintSched.Lot = Paint_Inspection.Lot
SELECT
PS.Lot,
PS.Qty Sched,
Painted,
Scratch,
PaintRun
FROM PaintSched PS
LEFT JOIN (SELECT
Lot,
SUM(QTYPainted) Painted
FROM Painted_Log GROUP BY Lot) PL
ON PS.Lot = PL.Lot
LEFT JOIN (SELECT
Lot,
SUM(CASE WHEN DID = 1 THEN 1 ELSE 0 END) Scratch,
SUM(CASE WHEN DID = 2 THEN 1 ELSE 0 END) PaintRun
FROM Paint_Inspection GROUP BY Lot) PI
ON PS.Lot = PI.Lot
Try that in SQL Fiddle
The code above uses conditional sum to roll up the defect count by type before joining that to the lot id. If you have more than 2 statuses, you will need to update the above code accordingly.
Two things:
You should have a group by in the subquery
When you alias the subquery, you don't join it properly
See the edits to your query below:
SELECT
PaintSched.Scheduled,
PaintSched.Lot,
PaintSched.qty,
PaintSched.Is_Painted,
Painted_Log.falloff
FROM PaintSched
INNER JOIN Painted_Log ON PaintSched.Lot = Painted_Log.lot
INNER JOIN MPA_Desc ON MPA_Desc.MPAID = PaintSched.MPAID
INNER JOIN (
SELECT lot, sum(Paint_Inspection.qty) as seds
FROM Paint_Inspection
WHERE Paint_Inspection.Status = '1'
GROUP BY Paint_Inspection.lot -- Missing GROUP BY
) AS seeds
ON PaintSched.Lot = seeds.Lot

SQL Server : update a table with values from same table based on IDs in a second table

I have a table called STOCK that I want to update that looks like this:
-------------------------
NUMBER | UNITS
-------------------------
NA13ALPK1010 | 9
NA13ALANA1010 | 11
NA13ALPK1065 | 4
NA13ALANA106 | 5
ON0003 XS | 1
AT3322 2 | 3
Based on a second table called PKGINV that looks like this:
----------------------------------------
PKGNUMBER | BOARDNUMBER
----------------------------------------
NA13ALPK1010 | NA13ALANA1010
NA13ALPK1065 | NA13ALANA106
First, I'd like to be able to do a SELECT with some type of join so that I can show UNITS from STOCK for both PKGNUMBER and BOARDNUMBER in PKGINV.
Then, I'd like to update UNITS in STOCK when PKGINV.PKGNUMBER = STOCK.NUMBER with the PKGINV.BOARDNUMBER UNITS from STOCK.
So after the update, NA13ALPK1010 would have UNITS of 11 (the UNITS from NA13ALANA1010) and NA13ALPK1065 would have UNITS of 5 (the UNITS from NA13ALANA106).
Thanks in advance for your help on this!
Your SELECT is simply a matter of joining the STOCK table twice:
SELECT
PKGNUMBER_Stock.UNITS AS PKGNUMBER_UNITS
,BOARDNUMBER_Stock.UNITS AS BOARDNUMBER_UNITS
FROM
PKGINV AS pkginv
JOIN STOCK AS PKGNUMBER_Stock ON PKGNUMBER_Stock.NUMBER = pkginv.PKGNUMBER
JOIN STOCK AS BOARDNUMBER_Stock ON BOARDNUMBER_Stock.NUMBER = pkginv.BOARDNUMBER
Likewise, the UPDATE statement should simply match the join set above:
UPDATE PKGNUMBER_Stock
SET PKGNUMBER_Stock.UNITS = BOARDNUMBER_Stock.UNITS
FROM
PKGINV AS pkginv
JOIN STOCK AS PKGNUMBER_Stock ON PKGNUMBER_Stock.NUMBER = pkginv.PKGNUMBER
JOIN STOCK AS BOARDNUMBER_Stock ON BOARDNUMBER_Stock.NUMBER = pkginv.BOARDNUMBER
You need to join Stock to PKGINV two times:
Update s
set s.UNITS = s2.UNITS
from STOCK s
join PKGINV p on s.NUMBER = p.PKGNUMBER
join STOCK s2 on p.BOARDNUMBER = s2.NUMBER

Combine results of two different records in one

I have an SQL data stored in a single table but with different type and I want to combine the result in one liner show in the example below. Anyone can give suggestion to this SQL query?
My SQL query to get this results:
SELECT NumValue, Label, Type
FROM (CustomPollerStatusTable
INNER JOIN CustomPollers ON (CustomPollerStatusTable.PollerID =
CustomPollers.CustomPollerID))
INNER JOIN Nodes ON (CustomPollerStatusTable.NodeID = Nodes.NodeID)
WHERE ((Nodes.Caption = 'fqdn') AND
(CustomPollers.Type = 'Student Info') AND
(CustomPollerStatusTable.NumValue > 89) AND
(NOT (CustomPollerStatusTable.Label LIKE '%.snapshot%')) AND
(NOT (CustomPollerStatusTable.Label LIKE '%aggr%')) AND
(NOT (CustomPollerStatusTable.Label = '/vol/scratch/'))
)
====================================
NumValue | Label | Type
====================================
90 | Student 1 | Student Info
10 | Student 1 | Student Class
====================================
The results that I would like to achieve:
==========================================================================
NumValue.Info | NumValue.Class | Label | Type.Info | Type.Class
==========================================================================
90 | 10 | Student 1 | Student Info | Student Class
==========================================================================
This should do it. Slightly different from nrathaus' answer. Obviously you can use as to change the column names to whatever you want.
select
s1.NumValue,
s2.NumValue,
s1.Label,
s1.Type,
s2.Type
from Student s1 inner join Student s2
on s1.Label = s2.Label
where s1.Type like '%Info'
and s2.Type like '%Class'
EDIT: Now that you have posted your select statement I think this might not work. Can you post the table structure?
EDIT2: This might work.
INSERT INTO TempTable(
NumValInfo,
Label,
TypeInfo)
SELECT
c.NumValue,
c.Label,
p.Type
FROM (CustomPollerStatusTable c INNER JOIN CustomPollers p
ON (c.PollerID = p.CustomPollerID))
INNER JOIN Nodes n
ON (c.NodeID = n.NodeID)
WHERE n.Caption = 'fqdn'
AND p.Type = 'Student Info'
AND c.NumValue > 89
AND NOT (c.Label LIKE '%.snapshot%')
AND NOT (c.Label LIKE '%aggr%')
AND NOT (c.Label = '/vol/scratch/')
AND p.Type like '%Info'
UPDATE TempTable set
NumValClass = c.NumValue,
TypeClass = p.Type
FROM (CustomPollerStatusTable c INNER JOIN CustomPollers p
ON (c.PollerID = p.CustomPollerID))
INNER JOIN Nodes n
ON (c.NodeID = n.NodeID)
INNER JOIN TempTable t
ON t.Label = c.Label
WHERE n.Caption = 'fqdn'
AND p.Type = 'Student Info'
AND c.NumValue > 89
AND NOT (c.Label LIKE '%.snapshot%')
AND NOT (c.Label LIKE '%aggr%')
AND NOT (c.Label = '/vol/scratch/')
AND p.Type like '%Class'
SELECT * FROM TempTable
I think this will do:
SELECT tblInfo.NumValue AS `NumValue.Info`,
tblClass.NumValue AS `NumValue.Class`,
Table.Label AS Label,
tblInfo.Type AS `Type.Info`,
tblClass.Type AS `Type.Class`
FROM (Table)
LEFT JOIN Table AS tblInfo ON tblInfo.Label = Table.Label ON tblInfo.Type = 'Student Info'
LEFT JOIN Table AS tblClass ON tblClass.Label = Table.Label ON tblClass.Type = 'Student Class'
GROUP BY Table.Label

Crosstab/cross over query

Given data looks like
PLI_ID OWN_ID DCSF_ID SCH_NAME PREMIUM1 PREMIUM2 DESCRIPTION
901 2 1000 Dfe-School 1 86.40 7.20 Heads, Deps
902 2 1000 Dfe-School 2 403.30 8.40 Relief Bursar
903 2 1000 Dfe-School 3 327.00 8.40 £10.00
904 2 1000 Dfe-School 4 381.50 8.40 £11.00
905 2 1000 Dfe-School 5 152.60 8.40 Teaching staff
Expected data to look like
School £10.00 £11.00 Heads, Deps Relief Bursar Teaching staff Total
Dfe-School 1
Dfe-School 2
Dfe-School 3
Dfe-School 4
Total [Pre-Total]
I am not sure whether to write a Cross Tab or Cross Over query, as suggested. Let me know, if need more explanation.
My query uses around 6 tables and it looks like this:
SELECT PolicyLine.PLI_POS_Id, Policy.POL_OWN_Id, Policy.POL_DCSF, School.SCH_Name, PolicyLine.PLI_Premium, CoverPremium.CPR_Premium, StaffCategory.SCA_Description FROM
School
INNER JOIN Policy ON School.SCH_OWN_Id = Policy.POL_OWN_Id AND School.SCH_DCSF = Policy.POL_DCSF
INNER JOIN PolicyLine ON Policy.POL_Id = PolicyLine.PLI_POL_Id
INNER JOIN CoverOption ON PolicyLine.PLI_COP_Id = CoverOption.COP_Id
INNER JOIN CoverPremium ON CoverOption.COP_Id = CoverPremium.CPR_COP_Id AND Policy.POL_OWN_Id = CoverPremium.CPR_OWN_Id
RIGHT OUTER JOIN StaffCategory ON CoverOption.COP_SCA_Id = StaffCategory.SCA_
Based on your existing query you would use something like this:
SELECT School.SCH_Name school,
[£10.00], [£11.00],
[Heads, Deps], [Relief Bursar], [Teaching staff]
FROM
(
SELECT PolicyLine.PLI_POS_Id,
Policy.POL_OWN_Id,
Policy.POL_DCSF,
School.SCH_Name,
PolicyLine.PLI_Premium,
CoverPremium.CPR_Premium,
StaffCategory.SCA_Description
FROM School
INNER JOIN Policy
ON School.SCH_OWN_Id = Policy.POL_OWN_Id
AND School.SCH_DCSF = Policy.POL_DCSF
INNER JOIN PolicyLine
ON Policy.POL_Id = PolicyLine.PLI_POL_Id
INNER JOIN CoverOption
ON PolicyLine.PLI_COP_Id = CoverOption.COP_Id
INNER JOIN CoverPremium
ON CoverOption.COP_Id = CoverPremium.CPR_COP_Id
AND Policy.POL_OWN_Id = CoverPremium.CPR_OWN_Id
RIGHT OUTER JOIN StaffCategory
ON CoverOption.COP_SCA_Id = StaffCategory.SCA_
) x
PIVOT
(
sum(PLI_Premium)
for SCA_Description in([£10.00], [£11.00],
[Heads, Deps], [Relief Bursar], [Teaching staff])
) p
See SQL Fiddle with Demo
You probably want a PIVOT query, but from your example it's hard to tell what that should look like.
SELECT *
FROM yourtable
PIVOT
(SUM(Premium) FOR sch_name in ([£10.00],[£11.00],[Heads, Deps],[Relief Bursar],[Teaching staff]))