Update field where the items are part of a subquery - sql

I am testing some software and need to make some adjustments to the fields manually. For all items that are produced at factory A, the lead time needs to be adjusted for the other factories those items are produced. However, the other items that are at the other factories need the normal leadtime.
I have the query to select the items that are produced at the alternate factories. I've tried using update where exists and having that be a subquery. I can't seem to get it to work as I feel it should
update newgdmoperation
set newgdmoperation.productionoffset = 75
where exists
(
select
newgdmoperation.operationid
from newgdmoperation
right join
(
select mainproductid,productionoffset
from newgdmoperation
where fromlocationid = 'KR'
and transporttype like 'Ves%'
) a
on newgdmoperation.mainproductid = a.mainproductid
where fromlocationid <> 'KR'
and transporttype like 'Ves%'
)
This doesn't give any error results. However, it updates the field for all item.
The subquery under the where clause does in fact return the operationid (unique id) for the items that need to be updated. I was expecting that with the where exists, that only the items in the subquery would be updated while the rest would be left untouched.

Assuming that you're trying to update the NEWGDMOPERATION table it looks to me like you should use IN rather than EXISTS, and so your statement should be
UPDATE NEWGDMOPERATION g
SET g.PRODUCTIONOFFSET = 75
WHERE g.OPERATIONID IN (SELECT g2.OPERATIONID
FROM NEWGDMOPERATION g2
RIGHT JOIN (SELECT g3.MAINPRODUCTID,
g3.PRODUCTIONOFFSET
FROM NEWGDMOPERATION g3
WHERE g3.FROMLOCATIONID = 'KR' AND
g3.TRANSPORTTYPE LIKE 'VES%') a
ON g2.MAINPRODUCTID = a.MAINPRODUCTID
WHERE g2.FROMLOCATIONID <> 'KR' AND
g2.TRANSPORTTYPE LIKE 'VES%')

Related

SQL Server - Need to SUM values in across multiple returned records

In the following query I am trying to get TotalQty to SUM across both the locations for item 6112040, but so far I have been unable to make this happen. I do need to keep both lines for 6112040 separate in order to capture the different location.
This query feeds into a Jasper ireport using something called Java.Groovy. Despite this, none of the PDFs printed yet have been either stylish or stained brown. Perhaps someone could address that issue as well, but this SUM issue takes priority
I know Gordon Linoff will get on in about an hour so maybe he can help.
DECLARE #receipt INT
SET #receipt = 20
SELECT
ent.WarehouseSku AS WarehouseSku,
ent.PalletId AS [ReceivedPallet],
ISNULL(inv.LocationName,'') AS [ActualLoc],
SUM(ISNULL(inv.Qty,0)) AS [LocationQty],
SUM(ISNULL(inv.Qty,0)) AS [TotalQty],
MAX(CAST(ent.ReceiptLineNumber AS INT)) AS [LineNumber],
MAX(ent.WarehouseLotReference) AS [WarehouseLot],
LEFT(SUM(ent.WeightExpected),7) AS [GrossWeight],
LEFT(SUM(inv.[Weight]),7) AS [NetWeight]
FROM WarehouseReceiptDetail AS det
INNER JOIN WarehouseReceiptDetailEntry AS ent
ON det.ReceiptNumber = ent.ReceiptNumber
AND det.FacilityName = ent.FacilityName
AND det.WarehouseName = ent.WarehouseName
AND det.ReceiptLineNumber = ent.ReceiptLineNumber
LEFT OUTER JOIN Inventory AS inv
ON inv.WarehouseName = det.WarehouseName
AND inv.FacilityName = det.FacilityName
AND inv.WarehouseSku = det.WarehouseSku
AND inv.CustomerLotReference = ent.CustomerLotReference
AND inv.LotReferenceOne = det.ReceiptNumber
AND ISNULL(ent.CaseId,'') = ISNULL(inv.CaseId,'')
WHERE
det.WarehouseName = $Warehouse
AND det.FacilityName = $Facility
AND det.ReceiptNumber = #receipt
GROUP BY
ent.PalletId
, ent.WarehouseSku
, inv.LocationName
, inv.Qty
, inv.LotReferenceOne
ORDER BY ent.WarehouseSku
The lines I need partially coalesced are 4 and 5 in the above return.
Create a second dataset with a subquery and join to that subquery - you can extrapolate from the following to apply to your situation:
First the Subquery:
SELECT
WarehouseSku,
SUM(Qty)
FROM
Inventory
GROUP BY
WarehouseSku
Now apply to your query - insert into the FROM clause:
...
LEFT JOIN (
SELECT
WarehouseSKU,
SUM(Qty)
FROM
Inventory
GROUP BY
WarehouseSKU
) AS TotalQty
ON Warehouse.WarehouseSku = TotalQty.WarehouseSku
Without seeing the actual schema DDL it is hard to know the exact cardinality, but I think this will point you in the right direction.

Conditional AND statement based on results of COUNT()

I'm getting lost in a query's logic, and I need some help. To start, I have a parent table Campaigns. Then, a child table CampaignParks that looks like this:
select * from CampaignParks
For business reasons I won't bore you with, we need to include Parks in the Campaign table even if they are not included in the Campaign. To actually include them in the campaign, there is a flag for that. None, one, or multiple Parks might be set to Include In Campaign.
Ok. Simple enough. Now...
Given a #ParkID, I need to return all parent Campaigns where the ParkID is a match, but ONLY if one (or more) of the IncludeInCampaign flags for the campaign has been set. If no IncludeInCampaign flags for a given campaign have been set, then we just ignore the value of #Parks. We don't care about it.
Examples:
#ParkID = 11070. We get back 4 & 1
#ParkID = 11526. We get back 1
#ParkID = 26496. We get back 1
#ParkID = null. We get back 4 & 1
ParkID = 69. We get back 1.
So, I think the query would look something like this:
SELECT
DISTINCT
sc.ContactID,
cp.*
FROM
Campaigns sc
JOIN CampaignParks cp on sc.CampaignID = cp.CampaignID
WHERE
((SELECT COUNT(*) FROM CampaignParks cp2 WHERE cp2.CampaignID = sc.CampaignID AND cp2.IncludeInCampaign = 1) > 0 OR cp.ParkID = #ParkID)
But, this isn't getting me the right results.
(I need to take my daughter to gymnastics... I'll take a look at relies when I get back. Thank you!!)
I think your code is close. The major difference is the AND versus OR in the WHERE clause:
SELECT sc.ContactID, cp.*
FROM Campaigns c JOIN
CampaignParks cp
on sc.CampaignID = cp.CampaignID
WHERE cp.ParkId = #ParkId AND
EXISTS (SELECT 1
FROM CampaignParks cp2
WHERE cp2.CampaignID = cp.CampaignID AND
cp2.IncludeInCampaign = 1
);

subquery returning more than one value

SELECT CG.SITEID,
CR.COLLECTIONID,
CG.COLLECTIONNAME,
CASE
WHEN CR.ARCHITECTUREKEY = 5
THEN
N'vSMS_R_System'
WHEN CR.ARCHITECTUREKEY = 0
THEN
(SELECT BASETABLENAME
FROM DISCOVERYARCHITECTURES
JOIN
COLLECTION_RULES
ON DISCOVERYARCHITECTURES.DISCARCHKEY =
COLLECTION_RULES.ARCHITECTUREKEY
JOIN
COLLECTIONS_G
ON COLLECTION_RULES.COLLECTIONID =
COLLECTIONS_G.COLLECTIONID
WHERE COLLECTIONS_G.SITEID = (SELECT TOP 1 SOURCECOLLECTIONID FROM VCOLLECTIONDEPENDENCYCHAIN WHERE DEPENDENTCOLLECTIONID = CG.SITEID ORDER BY LEVEL DESC))
ELSE (SELECT DA.BASETABLENAME FROM DISCOVERYARCHITECTURES DA WHERE DA.DISCARCHKEY=CR.ARCHITECTUREKEY) END AS TABLENAME
FROM COLLECTIONS_G CG
JOIN COLLECTIONS_L CL ON CG.COLLECTIONID=CL.COLLECTIONID
JOIN COLLECTION_RULES CR ON CG.COLLECTIONID=CR.COLLECTIONID
WHERE (CG.FLAGS&4)=4 AND CL.CURRENTSTATUS!=5
I am having a problem with the code above, around the line:
when cr.ArchitectureKey=0 then...
The problem is that the sub-query returns more than one value, and I'm not too sure how to invert the query so that I get rid of the error.
To make matters worse, cr.ArchitectureKey would normally join with da.DiscArchKey, but while cr.ArchitectureKey can have a value of 0, that does not exist in da.DiscArchKey, meaning if I join the two directly I lose data.
EDIT
More information regarding the problem itself:
This is a stored procedure for a Microsoft product that has a 'bug' (probably considered a feature though) which I'm trying to fix. Don't worry, this is only in my own little test server.
Anyway, there's the concept of a Collection. All Collections must have a parent (determined through VCOLLECTIONDEPENDENCYCHAIN), with the exception of the very top level Collection that is a system collection and cannot be modified.
Each collection can have 0 or more rules, and each rule has a rule type, where the ID of the rule type is saved onto COLLECTION_RULES and the matching string for that ID is saved onto DISCOVERYARCHITECTURES.
In most cases, a rule is a WQL query, and the rule type is determined by what tables are queried on the WQL query.
However, and this is where the problem lies, collections can also have a query of type 'include' or 'exclude', which basically forces it to borrow the query of another Collection. So effectively you include the results of another Collection's query onto your own Collection, and that's the query.
As far as COLLECTION_RULES is concerned, when that happens, the ID of the rule type is 0, which is a value that doesn't exist in DISCOVERYARCHITECTURES.
What I was trying to modify was so that when the rule type is 0, get and use the rule type(s) of the highest up parent (not the direct parent since the parent Collection could also have a single include rule, in which case the rule type would still be 0).
The problem is that because each rule can have multiple rule types, it returns multiple rows in some instances.
I tried to invert the query to remove the SELECT and use joins only, but failed because I found I always needed to join it to DISCOVERYARCHITECTURES and I have nothing to join it on when the rule type = 0.
EDIT2
Sample data:
Collections_G
Collections_L
Collection_Rules
DiscoveryArchitectures
vCollectionDependencyChain
Original Query and Original Results
SELECT cg.SiteID,
CASE
WHEN da.DiscArchKey=5
THEN N'vSMS_R_System'
ELSE da.BaseTableName END AS TableName
FROM Collections_G cg
JOIN Collections_L cl ON cg.CollectionID=cl.CollectionID
JOIN Collection_Rules cr ON cg.CollectionID=cr.CollectionID
JOIN DiscoveryArchitectures da ON cr.ArchitectureKey=da.DiscArchKey
WHERE (cg.Flags&4)=4 AND cl.CurrentStatus!=5
As you can see from the results picture above, some collections appear multiple times but with different TableNames. This is because each collection have have several rules, and each rule has one cr.ArchitectureKey
Also, and more importantly, collections PS10000B and PS10000C do not show up because their cr.ArchitectureKey = 0 which is a value that doesn't exist in da.DiscArchKey.
My goal is to have collections that have a cr.ArchitectureKey appear, but I need to assign them a cr.ArchitectureKey
My thought (which is slightly flawed, but don't know enough SQL to make it better, so if someone could help with that it would be appreciated too) was to get use the da.DiscArchKey from the top level parent. But the top level parent can have multiple DiscArchKeys, which is what is causing the problem.
As mentioned above getting the top level parent is slightly flawed, and ideally I would get the top level cr.ReferencedCollectionID. In other words, if PS10000B has a cr.ReferencedCollectionID of PS10000C and PS10000C has a cr.ReferencedCollectionID of SMS00002 but because SMS00002 has no cr.ReferencedCollectionID then SMS00002 is the top level cr.ReferencedCollectionID and both PS10000B and PS10000C should have da.DiscArchKey(s) equal to those of SMS00002.
Please have a look at a wired solution that comes into mind. You may face some syntax errors(most probably in 2nd and 3rd CTE) but it just an idea.
Get each case values in separate CTEs and then combine them at the end.
;WITH CTE
AS
(
SELECT CG.SITEID,
CR.COLLECTIONID,
CG.COLLECTIONNAME
FROM COLLECTIONS_G CG
JOIN COLLECTIONS_L CL ON CG.COLLECTIONID=CL.COLLECTIONID
JOIN COLLECTION_RULES CR ON CG.COLLECTIONID=CR.COLLECTIONID
WHERE (CG.FLAGS&4)=4 AND CL.CURRENTSTATUS!=5
),
ARCHITECTUREKEY5
AS
(
SELECT C.SITEID,
C.COLLECTIONID,
C.COLLECTIONNAME,
N'vSMS_R_System' as TABLENAME
FROM CTE C WHERE C.ARCHITECTUREKEY = 5
),
ARCHITECTUREKEY0
AS
(
SELECT C.SITEID,
C.COLLECTIONID,
C.COLLECTIONNAME,
BASETABLENAME as TABLENAME
FROM CTE C,
DISCOVERYARCHITECTURES
JOIN
COLLECTION_RULES
ON DISCOVERYARCHITECTURES.DISCARCHKEY =
COLLECTION_RULES.ARCHITECTUREKEY
JOIN
COLLECTIONS_G
ON COLLECTION_RULES.COLLECTIONID =
COLLECTIONS_G.COLLECTIONID
WHERE COLLECTIONS_G.SITEID = (SELECT TOP 1 SOURCECOLLECTIONID FROM VCOLLECTIONDEPENDENCYCHAIN WHERE DEPENDENTCOLLECTIONID = C.SITEID ORDER BY LEVEL DESC))
and C.ARCHITECTUREKEY = 0
),
ARCHITECTUREKEYOTHER
AS
(
SELECT C.SITEID,
C.COLLECTIONID,
C.COLLECTIONNAME,
DA.BASETABLENAME as TABLENAME
FROM DISCOVERYARCHITECTURES DA, CTE C WHERE DA.DISCARCHKEY=CR.ARCHITECTUREKEY AND C.ARCHITECTUREKEY not in (0,1)
)
Select * from ARCHITECTUREKEY5
UNION
Select * from ARCHITECTUREKEY0
UNION
Select * from ARCHITECTUREKEYOTHER

SQL Reporting count of parameter in a column

I am working in SSRS 3.0 with a SQL table including the following fields:
ApptID BookedBy ConfirmedBy CancelledBy
I also have a parameter setup to select which users to filter by (matches data in the BookedBy, ConfirmedBy and CancelledBy columns) called #Scheduler (which is a multi vale parameter/array).
I need to get a count for booked, confirmed and scheduled for how many times any value in the Scheduler parameter shows up in that column.
Basically:
COUNT(BookedBy IN (#Scheduler)) AS BookedCount
Can anyone help me out with the syntax for doing this?
Try this
SELECT Count(BookedBy = #Scheduler) as [BookedCount],
Count(ConfirmedBy = #Scheduler) as [ConfirmedCount],
Count(CancelledBy = #Scheduler) as [CancelledCount]
FROM tablename
WHERE BookedBy = #Scheduler OR
ConfirmedBy = #Scheduler OR
CancelledBy = #Scheduler
NB - Not tested might contain typos
If your input is a list separated by commas you can convert that to a table. See a reference like this:
http://www.projectdmx.com/tsql/sqlarrays.aspx
For this use case I'd recommend one of the solutions that saves the result in a CTE (since you only need to convert your input once and this will be fastest)
Then you could use that table (called sTable with column name) like this:
SELECT Count(Bo.Name) as [BookedCount],
Count(Co.Name) as [ConfirmedCount],
Count(Ca.Name) as [CancelledCount]
FROM tablename
LEFT JOIN sTable Bo ON BookedBy = Bo.name
LEFT JOIN sTable Co ON ConfirmedBy = Co.name
LEFT JOIN sTable Ca ON CancelledBy = Ca.name
I guess this will work but it does not seem as nice as the others:
SELECT (SELECT COUNT(*) FROM table WHERE BookedBy in (#Scheduler)) AS [BookedCount],
(SELECT COUNT(*) FROM table WHERE ConfirmedBy in (#Scheduler)) as [ConfirmedCount],
(SELECT COUNT(*) FROM table WHERE CancelledBy in (#Scheduler)) as [CancelledCount]

outer query to list only if its rowcount equates to inner subquery

Need help on a query using sql server 2005
I am having two tables
code
chargecode
chargeid
orgid
entry
chargeid
itemNo
rate
I need to list all the chargeids in entry table if it contains multiple entries having different chargeids
which got listed in code table having the same charge code.
data :
code
100,1,100
100,2,100
100,3,100
101,11,100
101,12,100
entry
1,x1,1
1,x2,2
2,x3,2
11,x4,1
11,x5,1
using the above data , it query should list chargeids 1 and 2 and not 11.
I got the way to know how many rows in entry satisfies the criteria, but m failing to get the chargeids
select count (distinct chargeId)
from entry where chargeid in (select chargeid from code where chargecode = (SELECT A.chargecode
from code as A join code as B
ON A.chargecode = B.chargeCode and A.chargetype = B.chargetype and A.orgId = B.orgId AND A.CHARGEID = b.CHARGEid
group by A.chargecode,A.orgid
having count(A.chargecode) > 1)
)
First off: I apologise for my completely inaccurate original answer.
The solution to your problem is a self-join. Self-joins are used when you want to select more than one row from the same table. In our case we want to select two charge IDs that have the same charge code:
SELECT DISTINCT c1.chargeid, c2.chargeid FROM code c1
JOIN code c2 ON c1.chargeid != c2.chargeid AND c1.chargecode = c2.chargecode
JOIN entry e1 ON e1.chargeid = c1.chargeid
JOIN entry e2 ON e2.chargeid = c2.chargeid
WHERE c1.chargeid < c2.chargeid
Explanation of this:
First we pick any two charge IDs from 'code'. The DISTINCT avoids duplicates. We make sure they're two different IDs and that they map to the same chargecode.
Then we join on 'entry' (twice) to make sure they both appear in the entry table.
This approach gives (for your example) the pairs (1,2) and (2,1). So we also insist on an ordering; this cuts to result set down to just (1,2), as you described.