Why is it not matching? - sql

Code:
(SELECT
[QBDATABASE].[dbo].[itemnoninventory].[FullName],
[LotTracker].[dbo].[tblParts].[PartNo],
[QBDATABASE].[dbo].[itemnoninventory].[CustomField2] AS StdCost,
[QBDATABASE].[dbo].[salesorpurchasedetail].[Price],
[QBDATABASE].[dbo].[itemnoninventory].[ListID],
[QBDATABASE].[dbo].[salesorpurchasedetail].[IDKEY]
FROM
[QBDATABASE].[dbo].[itemnoninventory]
Inner JOIN
[QBDATABASE].[dbo].[salesorpurchasedetail] ON [QBDATABASE].[dbo].[itemnoninventory].[ListID] = [QBDATABASE].[dbo].[salesorpurchasedetail].[IDKEY]
INNER JOIN
[LotTracker].[dbo].[tblParts] ON [QBDATABASE].[dbo].[itemnoninventory].[FullName] like [LotTracker].[dbo].[tblParts].[PartNo]
WHERE ([QBDATABASE].[dbo].[salesorpurchasedetail].[AccountRef_FullName] = 'Inventory, Raw Material')
I added unneeded selects to create the screenshot below of sample results.
ListID is varchar(255), null)
IDKEY is varchar(255), null)
Questions:
What would cause query to not see ListID = IDKEY for the NULL results?
EDIT Goal:
Stdcost should match the Price amount if ListID=IDKEY and FullName=PartNo

This isn't an answer but too long for a comment. Here your exact same query. The ONLY changes I made was a little formatting and removed all those horrifically long object names and used aliases instead.
SELECT
ini.FullName,
p.PartNo,
ini.CustomField2 AS StdCost,
spd.Price,
ini.ListID,
spd.IDKEY
FROM QBDATABASE.dbo.itemnoninventory ini
Inner JOIN QBDATABASE.dbo.salesorpurchasedetail spd ON ini.ListID = spd.IDKEY
INNER JOIN LotTracker.dbo.tblParts p ON ini.FullName like p.PartNo
WHERE spd.AccountRef_FullName = 'Inventory, Raw Material'
The answer to your question is that the row in itemnoninventory contain NULL so of course it will be NULL in the query.

After your edit, you need to have the price returned if CustomField2 is null. This can be done with either ISNULL or COALESCE. ISNULL will return the second value if the first value is null.
(SELECT
[QBDATABASE].[dbo].[itemnoninventory].[FullName],
[LotTracker].[dbo].[tblParts].[PartNo],
ISNULL([QBDATABASE].[dbo].[itemnoninventory].[CustomField2],[QBDATABASE].[dbo].[salesorpurchasedetail].[Price]) AS StdCost,
[QBDATABASE].[dbo].[salesorpurchasedetail].[Price],
[QBDATABASE].[dbo].[itemnoninventory].[ListID],
[QBDATABASE].[dbo].[salesorpurchasedetail].[IDKEY]
FROM
[QBDATABASE].[dbo].[itemnoninventory]
Inner JOIN
[QBDATABASE].[dbo].[salesorpurchasedetail] ON [QBDATABASE].[dbo].[itemnoninventory].[ListID] = [QBDATABASE].[dbo].[salesorpurchasedetail].[IDKEY]
INNER JOIN
[LotTracker].[dbo].[tblParts] ON [QBDATABASE].[dbo].[itemnoninventory].[FullName] like [LotTracker].[dbo].[tblParts].[PartNo]
WHERE ([QBDATABASE].[dbo].[salesorpurchasedetail].[AccountRef_FullName] = 'Inventory, Raw Material')

I cannot upvote. I combined both seans replies and have what I wanted. Ty both.
SELECT
ini.FullName,
p.PartNo,
ISNULL(ini.CustomField2,spd.Price) AS StdCost,
spd.Price,
ini.ListID,
spd.IDKEY
FROM QBDATABASE.dbo.itemnoninventory ini
Inner JOIN QBDATABASE.dbo.salesorpurchasedetail spd ON ini.ListID = spd.IDKEY
INNER JOIN LotTracker.dbo.tblParts p ON ini.FullName like p.PartNo
WHERE spd.AccountRef_FullName = 'Inventory, Raw Material'

Related

How to do operations between a column and a subquery

I would like to know how I can do operations between a column and a subquery, what I want to do is add to the field Subtotal what was obtained in the subquery Impuestos, the following is the query that I am using for this case.
Select
RC.PURCHID;
LRC.VALUEMST as 'Subtotal',
isnull((
select sum((CONVERT(float, TD1.taxvalue)/100)*LRC1.VALUEMST ) as a
FROM TAXONITEM TOI1
inner join TAXDATA TD1 ON (TD1.TAXCODE = TOI1.TAXCODE and RC.DATAAREAID = TD1.DATAAREAID)
inner join TRANS LRC1 on (LRC1.VEND = RC.RECID)
WHERE TOI1.TAXITEMGROUP = PL.TAXITEMGROUP and RC.DATAAREAID = TOI1.DATAAREAID
), 0) Impuestos
from VEND RC
inner join VENDTABLE VTB on VTB.ACCOUNTNUM = RC.INVOICEACCOUNT
inner join TRANS LRC on (LRC.VEND = RC.RECID)
inner join PURCHLINE PL on (PL.LINENUMBER =LRC.LINENUM and PL.PURCHID =RC.PURCHID)
where year (RC.DELIVERYDATE) =2021 and RC.PURCHASETYPE =3 order by RC.PURCHID;
Hope someone can give me some guidance when doing operations with subqueries.
A few disjointed facts that may help:
When a SELECT statement returns only one row with one column, you can enclose that statement in parenthesis and use it as a plain value. In your case, let's say that select sum(......= TOI1.DATAAREAID returns 500. Then, your outer select's second column is equivalent to isnull(500,0)
You mention in your question "subquery Impuestos". Keep in mind that, although you indeed used a subquery as we mentioned earlier, by the time it was enclosed in parentheses it is not treated as a subquery (more accurately: derived table), but as a value. Thus, the "Impuestos" is only a column alias at this point
I dislike and avoid subqueries before the from, makes things much harder to read. Here is a solution with apply which will keep your code mostly intact:
Select
RC.PURCHID,
LRC.VALUEMST as 'Subtotal',
isnull(subquery1.a, 0) as Impuestos
from VEND RC
inner join VENDTABLE VTB on VTB.ACCOUNTNUM = RC.INVOICEACCOUNT
inner join TRANS LRC on (LRC.VEND = RC.RECID)
inner join PURCHLINE PL on (PL.LINENUMBER =LRC.LINENUM and PL.PURCHID =RC.PURCHID)
outer apply
(
select sum((CONVERT(float, TD1.taxvalue)/100)*LRC1.VALUEMST ) as a
FROM TAXONITEM TOI1
inner join TAXDATA TD1 ON (TD1.TAXCODE = TOI1.TAXCODE and RC.DATAAREAID = TD1.DATAAREAID)
inner join TRANS LRC1 on (LRC1.VEND = RC.RECID)
WHERE TOI1.TAXITEMGROUP = PL.TAXITEMGROUP and RC.DATAAREAID = TOI1.DATAAREAID
) as subquery1
where year (RC.DELIVERYDATE) =2021 and RC.PURCHASETYPE =3 order by RC.PURCHID;

Query for updating a column in same table from same table

I have to update the authorid column which are matching (where documentculture = 'en-US'
to matching (where documentculture = 'el-GR' in the same table. which includes a inner join to another table
I written like below which looks wrong:
UPDATE t1
SET t1.authorid = t2.authorid
FROM wv_blogdata AS t1
INNER JOIN wv_blogdata AS t2
ON t1.documentnodeid = t2.documentnodeid
inner join CMS_Document d
ON d.BlogDataID = d.DocumentForeignKeyValue
WHERE t2.DocumentCulture = 'en-US';
could you please correct me?
More explanation:
select authorid from wv_blogdata
inner join CMS_Document
on wv_blogdata.BlogDataID = CMS_Document.DocumentForeignKeyValue
Where DocumentCulture ='el-GR'
The author id of above query is different from authorid of below query
which i want to make it synch
select authorid from wv_blogdata
inner join CMS_Document
on wv_blogdata.BlogDataID = CMS_Document.DocumentForeignKeyValue
Where DocumentCulture ='en-US'
As Zohar Peled says in the comments, unless you give sample data, expected results as well as your current DML it's hard to produce an accurate answer to your question.
That being said, in general terms if you can produce a select statement using table aliases that shows both the field to be updated and the field with the new value then you can use it as the basis for a successful UPDATE query.
So if the correct results are shown in this query(your original converted into a SELECT):
SELECT t1.authorid AS OldValue, t2.authorid AS NewValue
FROM wv_blogdata AS t1
INNER JOIN wv_blogdata AS t2
ON t1.documentnodeid = t2.documentnodeid
INNER JOIN CMS_Document d
ON d.BlogDataID = d.DocumentForeignKeyValue
WHERE t2.DocumentCulture = 'en-US';
you will get the correct outcome from this query(your original):
UPDATE t1
SET t1.authorid = t2.authorid
FROM wv_blogdata AS t1
INNER JOIN wv_blogdata AS t2
ON t1.documentnodeid = t2.documentnodeid
INNER JOIN CMS_Document d
ON d.BlogDataID = d.DocumentForeignKeyValue
WHERE t2.DocumentCulture = 'en-US';
Remembering of course to test your work for unexpected outcomes and hidden gotchas.
Again without sufficient sample data it's really hard to give you a definitive answer, so include as much detail as possible to help us help you.
Hope this helps you to work it out.
The following query should make the records in sync so authorid of german blogs and authorid of usa blogs will become the same after you run this query.
Note that top(1) is required so only one value is returned by the sub-query else if there are multiple blog records for german culture you will encounter an error.
UPDATE b
SET b.authorid =
(SELECT top(1) wvb.authorid
FROM wv_blogdata wvb
INNER JOIN CMS_Document cms ON wvb.BlogDataID = cms.DocumentForeignKeyValue
WHERE cms.DocumentCulture ='el-GR' AND b.BlogDataID = cms.DocumentForeignKeyValue order by wvb.authorid)
FROM wv_blogdata b
INNER JOIN CMS_Document ON b.BlogDataID = CMS_Document.DocumentForeignKeyValue
WHERE CMS_Document.DocumentCulture ='en-US';

Using COALESCE with JOIN on a different database column

Trying to populate the location column of a query and was hoping that the use of the COALESCE function would help me get what I want.
SELECT OrderItem.Code AS ItemCode, MAX(COALESCE(OrderItem.Location, [Picklist].[dbo].[ItemData].InventoryLocation)) AS Location, SUM(OrderItem.Quantity) AS Quantity, MAX(Store.StoreName) AS Store
FROM OrderItem
INNER JOIN [Order] ON OrderItem.OrderID = [Order].OrderID
INNER JOIN [Store] ON [Order].StoreID = [Store].StoreID
LEFT JOIN [AmazonOrder] ON [AmazonOrder].OrderID = [Order].OrderID
JOIN [Picklist].[dbo].[ItemData] ON [Picklist].[dbo].[ItemData].[InventoryNumber] = [OrderItem].[Code]
WHERE (CASE WHEN [Order].[LocalStatus] = 'Recently Downloaded' AND [AmazonOrder].FulfillmentChannel = 2 THEN 1
WHEN [Order].[LocalStatus] = 'Recently Downloaded' AND [Store].StoreName != 'Amazon' THEN 1 ELSE 0 END ) = 1
GROUP BY OrderItem.Code
ORDER BY ItemCode
There will not be a location when the Store is Amazon so I need to Join on another table in another database. I don't believe I'm using this correctly. Also I do get the right Location results returned if I use :
SELECT InventoryLocation From [Picklist].[dbo].[ItemData] WHERE InventoryNumber = 'L1201-2W-EA'
Perhaps this is more like the query that you want:
SELECT oi.Code AS ItemCode, COALESCE(oi.Location, id.InventoryLocation) AS Location,
oi.Quantity, s.StoreName AS Store
FROM OrderItem oi INNER JOIN
[Order] o
ON oi.OrderID = o.OrderID INNER JOIN
[Store]
ON o.StoreID = s.StoreID LEFT JOIN
AmazonOrder ao
ON ao.OrderID = o.OrderID JOIN
[Picklist].[dbo].[ItemData] id
ON id.InventoryNumber = oi.[Code]
WHERE o.LocalStatus = 'Recently Downloaded' AND
(ao.FulfillmentChannel = 2 OR s.StoreName <> 'Amazon')
ORDER BY ItemCode
Here are the changes:
Removed the aggregation. It does not seem to be part of the question.
Introduced table aliases, so the query is easier to write and to read.
Simplified the logic in the where clause.
As the comment above says, the max seems somewhat strange, an arbitrary aggregation no doubt due to one of the joins bringing back more information than you might of expected.
Then the statement has a few issues:
The coalesce is using two fields, neither if which is in a left join, only the AmazonOrder is left joined, so that seems a bit strange, that would only work if the first field in the coalesce (OrderItem.Location) is nullable - which it might be, there is no schema posted.
The left join itself is an inner join in disguise at present - within the where clause you have given explicit conditions on a field from that table - AND [AmazonOrder].FulfillmentChannel = 2 - if the record was actually missing the left join would return null for that field, and the where clause would then drop it out of the results. If you want this to properly work as a left join, any condition on fields from that table must move into the join condition, or the where clause itself must allow for that field being null (explicitly or using a coalesce.)
SELECT OrderItem.Code AS Code,
CASE WHEN (LEN(ISNULL(MAX([OrderItem].[Location]),'')) = 1)
THEN MAX([OrderItem].[Location])
ELSE MAX([Picklist].[dbo].[ItemData].InventoryLocation)
END AS Location,
SUM(OrderItem.Quantity) AS Quantity,
MAX(Store.StoreName) AS Store
FROM OrderItem
INNER JOIN [Order] ON OrderItem.OrderID = [Order].OrderID
INNER JOIN [Store] ON [Order].StoreID = [Store].StoreID
LEFT JOIN [AmazonOrder] ON [AmazonOrder].OrderID = [Order].OrderID
LEFT JOIN [Picklist].[dbo].[ItemData] ON [Picklist].[dbo].[ItemData].[InventoryNumber] = [OrderItem].[Code] OR
[Picklist].[dbo].[ItemData].[MediaCreator] = [OrderItem].[Code]
WHERE [Order].LocalStatus = 'Recently Downloaded' AND (AmazonOrder.FulfillmentChannel = 2 OR Store.StoreName <> 'Amazon')
GROUP BY OrderItem.Code
ORDER BY OrderItem.Code
Decided to go with case statement on location column route because I could not get COALESCE to work for me. Schema, some not all data, at SQLFiddle.
I guess if someone gets COALESCE to work I'll change the answer?
#Gordon Linoff I used the re-written WHERE clause because it looked cleaner than using the CASE statement. It worked and guessed there was a simpler way to go about it but was more worried about getting COALESCE to work. As for the Aliases sometimes I like to use them but in this case since there was a lot of tables I like to code out what I'm actually working in. Just my preference .

Retrieve additional rows if bit flag is true

I have a large stored procedure that is used to return results for a dialog with many selections. I have a new criteria to get "extra" rows if a particular bit column is set to true. The current setup looks like this:
SELECT
CustomerID,
FirstName,
LastName,
...
FROM HumongousQuery hq
LEFT JOIN (
-- New Query Text
) newSubQuery nsq ON hq.CustomerID = nsq.CustomerID
I have the first half of the new query:
SELECT DISTINCT
c.CustomerID,
pp.ProjectID,
ep.ProductID
FROM Customers c
JOIN Evaluations e (NOLOCK)
ON c.CustomerID = e.CustomerID
JOIN EvaluationProducts ep (NOLOCK)
ON e.EvaluationID = ep.EvaluationID
JOIN ProjectProducts pp (NOLOCK)
ON ep.ProductID = pp.ProductID
JOIN Projects p
ON pp.ProjectID = p.ProjectID
WHERE
c.EmployeeID = #EmployeeID
AND e.CurrentStepID = 5
AND p.IsComplete = 0
The Projects table has a bit column, AllowIndirectCustomers, which tells me that this project can use additional customers when the value is true. As far as I can tell, the majority of the different SQL constructs are geared towards adding additional columns to the result set. I tried different permutations of the UNION command, with no luck. Normally, I would turn to a table-valued function, but I haven't been able to make it work with this scenerio.
This one has been a stumper for me. Any ideas?
So basically, you're looking to negate the need to match pp.ProjectID = p.ProjectID when the flag is set. You can do that right in the JOIN criteria:
JOIN Projects p
ON pp.ProjectID = p.ProjectID OR p.AllowIndirectCustomers = 1
Depending on the complexity of your tables, this might not work out too easily, but you could do a case statement on your bit column. Something like this:
select table1.id, table1.value,
case table1.flag
when 1 then
table2.value
else null
end as secondvalue
from table1
left join table2 on table1.id = table2.id
Here's a SQL Fiddle demo

Find "missing" records in a bridge/data-intersect table

I'm generating images from an original and storing them in a table. I want a query that will check for gaps.
The image sizes are kept in a 3rd table, and each original should have 1 generated image for each record in the type table.
Where's what I've got so far:
SELECT oi.OriginalImageID, it.ImageTypeID
FROM dbo.OriginalImages AS oi
CROSS JOIN
dbo.ImageType AS it
LEFT OUTER JOIN
(
SELECT oi2.OriginalImageID, it2.ImageTypeID
FROM dbo.OriginalImages AS oi2
INNER JOIN
dbo.GeneratedImages AS gi2 ON gi2.OriginalImageID = oi2.OriginalImageID
INNER JOIN
dbo.ImageType AS it2 ON it2.ImageTypeID = gi2.ImageTypeID
) AS sub ON sub.OriginalImageID = oi.OriginalImageID
AND sub.ImageTypeID = it.ImageTypeID
WHERE (sub.OriginalImageID IS NULL)
Which works, but it seems very ugly. I'm wondering if there's a more elegant way to do it.
The tables essentially look like this:
OriginalImages
OriginalImageID (PK)
Image
GeneratedImages
OriginalImageID (FK)
ImageTypeID (FK)
Image
ImageType
ImageTypeID (PK)
Description
You should be able to simplify your existing query to:
SELECT oi.OriginalImageID, it.ImageTypeID
FROM dbo.OriginalImages AS oi
CROSS JOIN
dbo.ImageType AS it
LEFT OUTER JOIN
dbo.GeneratedImages AS gi2
ON gi2.OriginalImageID = oi.OriginalImageID AND
gi2.ImageTypeID = it.ImageTypeID
WHERE gi2.OriginalImageID IS NULL
Although personally I would use a NOT EXISTS:
SELECT oi.OriginalImageID, it.ImageTypeID
FROM dbo.OriginalImages AS oi
CROSS JOIN
dbo.ImageType AS it
WHERE NOT EXISTS
(SELECT NULL FROM dbo.GeneratedImages AS gi2
WHERE gi2.OriginalImageID = oi.OriginalImageID AND
gi2.ImageTypeID = it.ImageTypeID)
(Edited following comment.)