I am currently having to use two different queries to get back the results that I'm looking for. I have tried combining the two queries together, but that ends with me getting a large amount of extra(duplicates) data that I do not need. Below I have the working query listed.
SELECT p1.note as Itemcode,
order.ID as OrderNo,
piece1.ID As Piece1,
piece2.ID As Piece2,
i1.count as Unit,
unit.count as TotalUnits,
i1.rack as RackNo,
p1.EndDate as Piece1Finish,
p2.EndDate as Piece2Finish,
unit.group as BatchNo
FROM db.dbo.unit
JOIN db.dbo.order on order.entry_ID = unit.entry_ID
JOIN db.dbo.piece piece1 on piece1.ID_piece = unit.ID_piece_1
JOIN db.dbo.piece piece2 on piece2.ID_piece = unit.ID_piece_3
JOIN db.dbo.items i1 on i1.ID_unit = unit.ID_unit
JOIN db.dbo.items i2 on i2.ID_unit = unit.ID_unit
JOIN db.dbo.items i3 on i3.ID_unit = unit.ID_unit
JOIN db.dbo.items i4 on i4.ID_unit = unit.ID_unit
JOIN db.dbo.process p1 on p1.ID_process = i1.ID_process
JOIN db.dbo.process p2 on p2.ID_process = i2.ID_process
JOIN db.dbo.process p3 on p3.ID_process = i3.ID_process
JOIN db.dbo.process p4 on p4.ID_process = i4.ID_process
WHERE p1.note like '12A%'
and p1.ID_pieceorder = '1'
and p1.ID_job = '150'
and p2.ID_pieceorder = '3'
and p2.ID_job = '150'
and i1.count = i2.count
and i1.count = i3.count
and i1.count = i4.count
and i1.rack = i2.rack
and p1.note = p2.note
and i1.status = '1'
and i2.status = '1'
and p3.ID_pieceorder = '0'
and p4.ID_pieceorder = '2'
and p3.ID_job = '153'
and p4.ID_job = '151'
and i3.status = '0'
and i4.status = '0'
and order.status <> '4'
ORDER BY OrderNo
This query works fine. The second set of data I query to find adds the following information
SELECT ...(same as above)
FROM ...(same as above plus the following)
JOIN db.dbo.items i5 on i5.ID_unit = unit.ID_unit
JOIN db.dbo.items i6 on i6.ID_unit = unit.ID_unit
JOIN db.dbo.process p5 on p5.ID_process = i5.ID_process
JOIN db.dbo.process p6 on p6.ID_process = i6.ID_process
WHERE p1.note like '12B%'
and ... (same as above plus the following)...
and p5.ID_pieceorder = '1'
and p5.ID_job = '152'
and p6.ID_pieceorder = '3'
and p6.ID_job = '152'
and i5.status = '1'
and i6.status = '1'
and i1.count = i5.count
and i1.count = i6.count
When I try to make a combined query, the table joins of i5, i6, p5, and p6 produce a massive amount of duplicated results for p1.note like '12A%' due to it not needing the fields. Is there a method where I can initiate a join in the WHERE statement so that it will only use those two tables when p1.note like '12B%'? Something along the lines of
SELECT ....
FROM ....
WHERE (p1.note like '12A%'
or
(p1.note like '12B%'
and p5.ID_pieceorder = '1'
and p5.ID_job = '152'
and p6.ID_pieceorder = '3'
and p6.ID_job = '152'
and i5.status = '1'
and i6.status = '1'
and i1.count = i5.count
and i1.count = i6.count
(JOIN db.dbo.items i5 on i5.ID_unit = unit.ID_unit
JOIN db.dbo.items i6 on i6.ID_unit = unit.ID_unit
JOIN db.dbo.process p5 on p5.ID_process = i5.ID_process
JOIN db.dbo.process p6 on p6.ID_process = i6.ID_process)))
I know that the syntax above will not work, but I am looking for a method similar to that.
**EDIT FOR TABLE STRUCTURE requested by DRapp
I'm going to fill out the results I get with ID_unit 782327
-db.dbo.items-
-ID_item- -ID_process- -count- -status- -rack- -ID_unit-
628335 782328 1 0 25 782327
628336 782330 1 1 25 782327
628337 782331 1 1 25 782327
628338 782333 1 0 25 782327
628339 782335 1 1 25 782327
628340 782336 1 1 25 782327
628341 782337 1 0 25 782327
-db.dbo.process-
-ID_process- -ID_unit- -ID_pieceorder- -ID_job- -sequence-
782328 782327 0 50 1
782329 782327 1 5305 1
782330 782327 1 150 1
782331 782327 1 152 2
782332 782327 2 5408 2
782333 782327 2 151 1
782334 782327 3 5308 3
782335 782327 3 150 1
782336 782327 3 152 2
782337 782327 0 153 4
-db.dbo.unit-
-ID_unit- -status- -ID_piece_1- -ID_piece_2--ID_piece_3--ID_product-count
782327 2 5305 5408 5308 50 1
db.dbo.items contains a unique key for each "item" that goes into a part, it contains the corresponding process code, the "count" field, the "status" of each "item", the rack for each "item", and the unit ID of each "ITEM".
db.dbo.process contains the unique key for each "process", the ID_unit, ID_pieceorder, ID_job, and the sequence. Each unit starts with ID_pieceorder 0 which is establishing the product type, then ID_piece 1 for the first piece, etc..
db.dbo.unit contains the unique key for each "unit", the codes for all its pieces, the status of the unit, and count which is the number of units.
db.dbo.piece is a table with the master list of codes on it.
-ID_Piece- -Desc-
5305 14black
5408 14blue
150 Cut
The point of needing 6 processes is as follows
p1 & i1: Making sure the Piece is Piece 1, is process 150, and that process 150 is complete
p2 & i2: Making sure the piece is piece 2, is process 150, and that process 150 is complete
p3 & i3: Making sure it the completion process, 153, is not completed.
p4 & i4: making sure the connector process, 152, isn't completed(hasn't connected the two pieces).
p5 & i5: some pieces require extra work done, this checks and makes sure that process, 152, is completed on piece 1.
P6 & i6: The same as p5 & i5 but for piece 2.
if you don't want duplicates use a Union in between them, move you order by clause to the bottom of the second one. Make sure you select columns are in the same order in both statements.
select (your columns)
From (tables and joins)
where (your where)
UNION
select (your columns)
From (tables and joins)
where (your where)
order by
Per chatroom clarification, I have come up with the the following for you to start with and minimally adjust as needed.
SELECT
u.id_unit,
u.count as TotalUnits,
u.group as BatchNo,
p1.ID_PieceOrder as Piece1Order,
p1Cut.ID_Process as Piece1CutProcessID,
i1Cut.Count as Item1CutCount,
i1Cut.Status as Item1CutStatus,
p1Tamp.ID_PieceOrder as Piece1OrderTampered,
p1Tamp.ID_Process as Piece1TamperedProcessID,
i1Tamp.Count as Item1TamperedCount,
i1Tamp.Status as Item1TamperedStatus,
p2.ID_PieceOrder as Piece2Order,
p2Cut.ID_Process as Piece2CutProcessID,
i2Cut.Count as Item2CutCount,
i2Cut.Status as Item2CutStatus,
p2Tamp.ID_PieceOrder as Piece2OrderTampered,
p2Tamp.ID_Process as Piece2TamperedProcessID,
i2Tamp.Count as Item2TamperedCount,
i2Tamp.Status as Item2TamperedStatus,
pSpacer.ID_PieceOrder as SpacerPieceOrder,
iSpacer.Count as SpacerCount,
iSpacer.Status as SpacerStatus,
pSealed.ID_PieceOrder as SealedPieceOrder,
iSealed.Count as SealedCount,
iSealed.Status as SealedStatus
FROM
db.dbo.unit u
JOIN Process p1
ON u.ID_Unit = p1.ID_Unit
AND u.ID_Piece_1 = p1.ID_Job
JOIN Process p1Cut -- ALL PIECES MUST BE CUT first
ON p1.ID_Unit = p1Cut.ID_Unit
AND p1.ID_PieceOrder = p1Cut.ID_PieceOrder
AND p1Cut.ID_Job = 150
JOIN Items i1Cut
ON p1Cut.id_process = i1Cut.id_process
LEFT JOIN Process p1Tamp -- NOT ALL PIECES MUST BE TEMPERED
ON p1Cut.ID_Unit = p1Tamp.ID_Unit
AND p1Cut.ID_PieceOrder = p1Tamp.ID_PieceOrder
AND p1Tamp.ID_Job = 152
LEFT JOIN Items i1Tamp
ON p1Tamp.id_process = i1Tamp.id_process
JOIN Process p2
ON u.ID_Unit = p2.ID_Unit
AND u.ID_Piece_3 = p2.ID_Job
JOIN Process p2Cut -- ALL PIECES MUST BE CUT first
ON p2.ID_Unit = p2Cut.ID_Unit
AND p2.ID_PieceOrder = p2Cut.ID_PieceOrder
AND p2Cut.ID_Job = 150
JOIN Items i2Cut
ON p2Cut.id_process = i2Cut.id_process
LEFT JOIN Process p2Tamp -- NOT ALL PIECES MUST BE TEMPERED
ON p2Cut.ID_Unit = p2Tamp.ID_Unit
AND p2Cut.ID_PieceOrder = p2Tamp.ID_PieceOrder
AND p2Tamp.ID_Job = 152
LEFT JOIN Items i2Tamp
ON p2Tamp.id_process = i2Tamp.id_process
LEFT JOIN Process PSpacer
ON u.ID_Unit = PSpacer.ID_Unit
AND u.ID_Job = 151
LEFT JOIN Items ISpacer
ON PSpacer.ID_Process = ISpacer.ID_Process
LEFT JOIN Process PSealed
ON u.ID_Unit = PSealed.ID_Unit
AND u.ID_Job = 153
LEFT JOIN Items ISealed
ON PSealed.ID_Process = ISealed.ID_Process
WHERE
u.ID_Unit IN (782327, 782328, 782329 )
-- just a sample of 3 unit IDs to test concept of the revised query structure
I started at the unit table. From that, I am taking each piece down its respective path... First to get the piece, then from the piece, its CUT which will always be required. From the CUT to its ITEM status record which will always exist. From the CUT, I am then looking for a TAMPERED status for the same piece order. Since not all glass needs to be tampered, I have this as a LEFT-JOIN. I then LEFT-JOIN to the tampered's item record by the process id.
I do the same for the SECOND piece.
Then, a LEFT-JOIN to see IF there is a spacing required (can change to JOIN if spacer is ALWAYS required)
Finally, a LEFT-JOIN on the job completed entry. Again, don't know if all the entries are pre-filled in up-front for ALL stages of the process vs not.
Notice my alias name reference from P1 for the process for piece 1, then the p1Cut to i1Cut, to p1Tamp to i1Tamp. So now, instead of generic p1-p6, I have context to the process or item. Additionally, I just grabbed all the columns from the respective piece, cut, tampered, spacer and sealed steps with clear column names. If you don't want something you can always remove it, but with this, you SHOULD never get any duplicates per a single UNIT.
I did not add the join to the order or piece tables respectively. I don't know if piece is really needed unless you had other columns such as the P1.Name, but your table structure dump showed the description.
Since I did not add any other qualifiers, you should get the entire status of a single UNIT in one row. I would adjust the WHERE clause to pick a range of a few units you can test and confirm the context. THEN, adjust the where clause to look for your other criteria such as an item count = another or not, or piece within your '%a%' context or not. However, I THINK this will get you well on your way.
Something like this
LEFT JOIN db.dbo.process p1
on p1.ID_process = i1.ID_process
and p1.note like '12A%'
and p1.ID_pieceorder = '1'
and p1.ID_job = '150'
and p2.ID_pieceorder = '3'
and p2.ID_job = '150'
and i1.count = i2.count
and i1.count = i3.count
and i1.count = i4.count
and i1.rack = i2.rack
and p1.note = p2.note
and i1.status = '1'
and i2.status = '1'
and p3.ID_pieceorder = '0'
and p4.ID_pieceorder = '2'
and p3.ID_job = '153'
and p4.ID_job = '151'
LEFT JOIN db.dbo.items i5
on i5.ID_unit = unit.ID_unit
and p1.note like '12B%'
and i5.status = '1'
Related
Have two queries , one collects moves in based on property and unit type the other would collect based on Move Outs for the same data. when ran separately they yield the correct information (move outs are 6 and move ins are 11) Have tried nesting in select and from statements but not getting what i need. When nested within the select am getting the correct move outs per unit type, but each line for move ins is total move ins. I recall that the nesting here would only return one value but know there is a way to return the value for each row. Any assistance is appreciated.
SELECT
p.scode as PropNumber,
p.saddr1 propname,
ut.scode as UnitType,
COUNT(t.hmyperson) as Moveouts,
(
SELECT COUNT(t.hmyperson) as MoveIns
FROM
tenant t
JOIN unit u ON t.hunit = u.hmy
JOIN property p ON p.hmy = u.hproperty
JOIN unittype ut ON ut.hmy = u.HUNITTYPE
WHERE
t.dtmovein >= getdate() - 14
AND p.scode IN ('gsaff')
) mi
FROM
Property p
JOIN unit u ON u.hproperty = p.hmy
JOIN tenant t ON t.hunit = u.hmy
JOIN unittype ut ON ut.hmy = u.HUNITTYPE
WHERE
p.scode IN ('gsaff')
AND t.DTMOVEOUT >= getdate()- 14
GROUP BY
ut.scode,
p.scode,
p.saddr1
With this data is coming out like :
PropNumber Propname UnitType MoveOuts MoveIns
1 x tc2 1 11
1 x tc3 2 11
1 x tc4 1 11
1 x tc5 1 11
1 x tc6 1 11 <pre>
Move in column should display as
2
5
1
0
3
You need to correlate the subquery according to the record being processed in the outer query. This also requires that you use different table aliases in the subquery than in the outer query.
It is hard to tell without seeing sample data, however I would expect that you need to correlate with all non-aggregated columns in the outer query.
Try changing :
(
SELECT COUNT(t.hmyperson) as MoveIns
FROM
tenant t
JOIN unit u ON t.hunit = u.hmy
JOIN property p ON p.hmy = u.hproperty
JOIN unittype ut ON ut.hmy = u.HUNITTYPE
WHERE
t.dtmovein >= getdate() - 14
AND p.scode IN ('gsaff')
) mi
To :
(
SELECT COUNT(t.hmyperson) as MoveIns
FROM
tenant t1
JOIN unit u1 ON t1.hunit = u1.hmy
JOIN property p1 ON p1.hmy = u1.hproperty
JOIN unittype ut1 ON ut1.hmy = u1.HUNITTYPE
WHERE
t1.dtmovein >= getdate() - 14
AND p1.scode IN ('gsaff')
AND p1.scode = p.scode
AND p1.saddr1 = p.saddr1
AND ut1.scode = ut.scode
) mi
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
Hi i have joined to tables the code is below. Notice I have used A.Manad = B.Manad which joins data where the month of table A and B is equal. But sometimes table B dont have any data for that month. My code just skip the data, i would rather it just leave it empty or with a value of 0.
The Code takes a list of Orgnr which is swedish for company numbers and joins two tables where the orgnr is the same and the month is the same, but for some reason it doesnt join the data when the value is empty for one company. I still want the orgnr to show up in the joint table.
select Tillnr = A.tillnr, Orgnr = A.orgnr, Månad = A.Manad, Intrastat =
A.varde,Moms = B.vardeutf
into #Tabell1
From
IntrastatFsum A
left outer join
Momsuppg B
on A.Orgnr = B.Orgnr
where A.Orgnr in(
165563137933,165020456017,.......)
AND A.Ar = 2017
AND B.Ar = A.AR
AND A.Manad = 9
AND A.Manad = B.Manad
AND A.InfUtf = 'U'
You should move your WHERE clause AND A.Manad = B.Manad and AND B.Ar = A.AR to the LEFT JOIN clause.
In this way you will preserve all data from table IntrastatFsum:
select Tillnr = A.tillnr, Orgnr = A.orgnr, Månad = A.Manad, Intrastat =
A.varde,Moms = B.vardeutf
into #Tabell1
From
IntrastatFsum A
left outer join
Momsuppg B
on A.Orgnr = B.Orgnr
AND A.Manad = B.Manad
AND A.AR = B.Ar
where A.Orgnr in(
165563137933,165020456017,.......)
AND A.Ar = 2017
AND A.Manad = 9
AND A.InfUtf = 'U'
I have 3 tables: firearms_firearmbook, inventory_inventory and inventory_inventorytransaction.
And i have 2 Cases:
If inventory_inventory Table has no inventory_inventorytransaction with item action of 16, show inventory_inventory record
If inventory_inventory Table has inventory_inventorytransaction with item action of 16, show inventory_inventory and inventory_inventorytransaction.item_action_id
The query bellow works for the first cause, but its not working for the second cause.
It should show smth like this:
-----------------------------------
| id | serial | action_id |
-----------------------------------
1 MAGUM
2 EAGLE
2 EAGLE 16
Query:
SELECT FB.id, INV.serial_number, INV.id, INVT.item_action_id FROM firearms_firearmbook AS FB
LEFT JOIN inventory_inventory AS INV ON INV.id = FB.item_id
LEFT JOIN inventory_inventorytransaction AS INVT ON INVT.item_id = INV.id AND INVT.item_action_id = 16
WHERE FB.store_id = 1
It seems that if there is an action 16 record for a given item, you need two records in the output: one with a blank in the third column, and one with 16 in the third column.
In that case you could do this:
with base as (
select fb.id,
inv.serial_number,
inv.id,
from firearms_firearmbook as fb
inner join inventory_inventory as inv
on inv.id = fb.item_id
where fb.store_id = 1
)
select base.*,
invt.item_action_id
from base
inner join inventory_inventorytransaction as invt
on invt.item_id = base.id
and invt.item_action_id = 16
union all
select base.*,
null
from base
order by 1, 2, 3, 4 desc
Hi I think this is what your after.
I've made a CASE statement for the two situation you describe. I wasn't sure what you column you wanted for 2) when you say "inventory_inventory" so I put the id column and you can change it for another column.
I've also removed INVT.item_action_id = 16 part of the inventory_inventorytransaction join as I don't think it's necessary as it is handled in the CASE statement.
SELECT
FB.id,
INV.serial_number,
INV.id,
INVT.item_action_id,
CASE
WHEN INVT.item_action_id = 16 THEN CAST(INV.id as VARCHAR) + ' ' + CAST(INVT.item_action_id as VARCHAR) -- This is Case 2
ELSE INV.record -- This is Case 1
END as answer
FROM firearms_firearmbook AS FB
LEFT JOIN inventory_inventory AS INV ON INV.id = FB.item_id
LEFT JOIN inventory_inventorytransaction AS INVT ON INVT.item_id = INV.id -- Removed JOIN on INVT.item_action_id = 16 and moved it to CASE
WHERE FB.store_id = 1;
I'm attempting to get a Count of how many times each book occurs in the SurveyDatas table for a each grade and each survey year.
In the query below the result in the Grade3 column for BookId 300 should actually be 1, but instead its 116. And same for the Grade4 column too. If I remove the Grade4 Count and JOIN, I get 58 which is half of 116, but still incorrect. I'm suspicious I need to use a Subquery instead of Left Joins for what I'm trying to do here, or perhaps there's even a more efficient way of doing this. Would SQL Server Common Table Expressions help me out here? I've never used that feature.
SELECT sd.SurveyYear, sd.BookId,
Count(sd3.Grade) as Grade3, Count(sd4.Grade) as Grade4
FROM SurveyDatas sd
LEFT JOIN SurveyDatas sd3 on sd3.BookId = sd.BookId
AND sd3.SurveyYear = sd.SurveyYear
AND sd3.Grade = '3'
LEFT JOIN SurveyDatas sd4 on sd4.BookId = sd.BookId
AND sd4.SurveyYear = sd.SurveyYear
AND sd4.Grade = '4'
GROUP BY sd.SurveyYear, sd.BookId
And here's my table structure and what my data looks like, although I do have more data entered than what I'm showing here.
SurveyDataId | SurveyYear | BookId | Grade
1 2014 300 3
2 2014 300 4
You are getting a cartesian product between the two. Instead, just use conditional aggregation:
SELECT sd.SurveyYear, sd.BookId,
sum(case when sd.Grade = '3' then 1 else 0 end) as Grade3,
sum(case when sd.Grade = '4' then 1 else 0 end) as Grade4
FROM SurveyDatas sd
GROUP BY sd.SurveyYear, sd.BookId;
The self-join is not necessary.
When you self join, you need to consider all columns. You aren't using the SurverDataID, and not getting the full picture because of it. Include it in you join condition, and you'll see what you expect.
SELECT sd.SurveyYear, sd.BookId,
Count(sd3.Grade) as Grade3, Count(sd4.Grade) as Grade4
FROM SurveyDatas sd
LEFT JOIN SurveyDatas sd3 on sd3.BookId = sd.BookId
AND sd3.SurveyYear = sd.SurveyYear
AND sd3.Grade = '3'
AND sd.SurveyDataID = sd3.SurveyDataID -- Add this line
LEFT JOIN SurveyDatas sd4 on sd4.BookId = sd.BookId
AND sd4.SurveyYear = sd.SurveyYear
AND sd4.Grade = '4'
AND sd.SurveyDataID = sd4.SurveyDataID -- And also this line
GROUP BY sd.SurveyYear, sd.BookId
When I was trouble shooting it, I removed the group by so that I could see all the rows. I should have seen nulls for Grade 4 where the survey was for Grade 3, and that tipped me off to the real cause.