Counting items on tables - sql

I need your help. I have this code to query my machines which are on rental, on stock, and on my outlets, but this only works if I input an itemID, which means it will only query one item at a time. I need to query the number of machines on rental and on outlets, parallel to the number of stock on hand.
alter procedure GetItemsForQueries
#itemID varchar(15)
as begin
select i.ItemName, m.MachineModel, i.SellingPrice, i.QuantityOnHand,
(select COUNT(*) from ClientMachine where AcquisitionType = 'Rental' and ItemID = #itemID) as 'Quantity on Rentals',
(select COUNT(*) from OutletMachine where ItemID = #itemID) as 'Quantity on Outlets'
from Item i inner join Machine m on (m.ItemID = i.ItemID)
where i.ItemID = #itemID
end

Two subqueries should do it - something like this...
In a nutshell, find all the machines, join against a subquery which finds the count id thats rental and join again against another subquery that finds the count per outlet machine...
select m.itemid,
ifnull(ccount,0) as rental_count,
ifnull(ocount,0) as outlet_count
from Machine m
left join (select itemid,
count(*) as ccount
from ClientMachine
where AcquisitionType = 'Rental' group by ItemID) a1 on (a1.itemid=m.itemid)
left join (select itemid,
count(*) as ocount
from OutletMachine group by ItemID) a2 on (a2.itemid=m.itemid)

Of the top of my head (could have some syntax errors but the logic is there)
select i.ItemId, i.ItemName, m.MachineModel, i.SellingPrice, i.QuantityOnHand, rental.rentalCount, outlet.outletCount
from Item i
left join (select ItemId, count(*) as 'rentalCount' from ClientMachine Where AcquisitionType = 'Rental' group by ItemId) rental on rental.ItemId = i.ItemId
left join (select ItemId, count(*) as 'outletCount' from OutletMachine group by ItemId) outlet on outlet.ItemId = i.ItemId
inner join Machine m on (m.ItemID = i.ItemID)

Check this code :
select i.ItemName,
m.MachineModel,
i.SellingPrice,
i.QuantityOnHand,
(select COUNT(*) from ClientMachine where AcquisitionType = 'Rental' and ItemID = i.ItemID) as 'Quantity on Rentals',
(select COUNT(*) from OutletMachine where ItemID = i.ItemID) as 'Quantity on Outlets'
from Item i inner join Machine m on (m.ItemID = i.ItemID)

Related

DISTINCT return same ID two times wrongly

This is my SQL query:
SELECT DISTINCT(ItemId), TCode, PartNumber,ModelNumber, ItemUOM
FROM #Results
This query returns:
ItemId TCode Source PartNumber ModelNumber ItemUOM
-----------------------------------------------------------------
1024 1000 NULL NULL EA
1024 1000 FLEX FLEX EA
#Result is a temp table I have used left join in that query
Why does SELECT DISTINCT return the same ItemID 1024 twice?
SELECT DISTCINT(I.ItemId),
(DENSE_RANK() OVER(ORDER BY I.ItemId ASC)) AS RowNumber,
(I.TCode), E.Name AS Source,
I.GoldenRecordNumber AS GoldenRecordNo, I.ItemCode AS MMRefNo,
I.ShortDescription AS ShortText, I.LongDescription AS POText,
Suppliers.Description AS Manufacturer, Suppliers.Name AS ManufacturerCode,
Suppliers.Abbreviation AS ManufacturerAbbr,
ItemSuppliers.ReferenceNo AS PartNumber, ItemSuppliers.ReferenceNo AS ModelNumber,
UOM.Name AS ItemUOM, MG.Name AS PSGC,
NM.Noun AS ClassName, NM.LongAbbrevation AS ClassDescription
INTO
#Results
FROM
Items I
LEFT JOIN
ItemSuppliers ON I.ItemId = ItemSuppliers.ItemsId
LEFT JOIN
Suppliers ON ItemSuppliers.ManufacturerId = Suppliers.SupplierId
LEFT JOIN
UnitOfMeasurement UOM ON UOM.UOMId = I.UOMId
LEFT JOIN
MaterialGroup MG ON MG.MaterialGroupId = I.MaterialGroupId
LEFT JOIN
NounModifiers NM ON NM.NounModifierId = I.NounModifierId
LEFT JOIN
AutoClass AC ON AC.ClassName = NM.Noun
LEFT JOIN
ERP E ON E.ERPId = I.ERPName
LEFT JOIN
NounModifierAttributes NMA ON NMA.NounModifierId =
NM.NounModifierId
LEFT JOIN
Attributes A ON A.AttributeId = NMA.AttributeId
LEFT JOIN
ItemAttributes IA ON IA.ItemId = I.ItemId
WHERE
(I.ItemCode LIKE '%'+'2001010088'+'%' )
SELECT 'Int' = COUNT(distinct(ItemId))
FROM #Results
WHERE (TCode IS NOT NULL OR MMRefNo IS NOT NULL)
SELECT DISTINCT(ItemId),
TCode, Source, GoldenRecordNo, MMRefNo, ShortText, POText,
Manufacturer, ManufacturerCode, ManufacturerAbbr, PartNumber, ModelNumber,
ItemUOM, PSGC, ClassName, ClassDescription
FROM
#Results
WHERE
(TCode IS NOT NULL OR MMRefNo IS NOT NULL)
AND RowNumber BETWEEN (1-1)*100 + 1 AND (((1-1) * 100 + 1) + 100) - 1
DROP TABLE #Results
if you are convinced the rows which are selected can be grouped together then it should work fine.
1. but if rows are having different data then distinct will not help.
2. use ltrim,rtrim to remove leading and trailing spaces.
example: distinct(ltrim(rtrim(ItemId)))
this will help if it due to spaces or for junk values
The behavior of DISTINCT works as expected. For instance, you could use GROUP BY clause to group them by ItemId, TCode to get top most records
SELECT
ItemId, TCode,
MAX(PartNumber) PartNumber, MAX(ModelNumber) ModelNumber,
MAX(ItemUOM), ...
FROM #Results
GROUP BY ItemId, TCode
In case any failure in GROUP BY clause use ranking function to assign the rank and get the record based on rank value.

SQL Select Query into another query

I am a beginner with SQL so apologise in advance if my terminology / coding is a little off, or maybe way off.
I have two queries which I would like to join into one. The first creating a list of productids which contain two specific processes.
I then want to use these productids in the second query.
Also is below correct?
group by products.productid having (sum(case when processid like 'pick%' then 1 else 0 end) + sum(case when processid like 'pack%' then 1 else 0 end) = 2)
Any help would be much appreciated, hope this makes sense.
SELECT
Products.ProductID
FROM Products
INNER JOIN Categories ON Products.Category = Categories.Category
INNER JOIN Boms ON Products.Product = Boms.Product AND Boms.BomVersion = Products.BomVersion
LEFT OUTER JOIN Products AS Comp ON Boms.Component = Comp.Product
LEFT OUTER JOIN Processes ON Boms.Process = Processes.Process
WHERE
products.active = 1
and Categorys.Categoryid in ('5','20')
group by products.productid
having (sum(case when processid like 'pick%' then 1 else 0 end) + sum(case when processid like 'pack%' then 1 else 0 end) = 2)
order by products.productid
SELECT
Products.ProductID,
Products.productdescription,
Boms.Type As Type,
Comp.ProductId as Component,
Comp.productdescription,
Boms.Quantity,
BomVersions.BomVersionID,
Processes.processid,
Processes.ProcessDescription
FROM Products
INNER JOIN Categories ON Products.Category = Categories.Category
INNER JOIN Boms ON Products.Product = Boms.Product AND Boms.BomVersion = Products.BomVersion
LEFT OUTER JOIN Products AS Comp ON Boms.Component = Comp.Product
LEFT OUTER JOIN Processes ON Boms.Process = Processes.Process
INNER JOIN BomVersions ON Products.BomVersion = BomVersions.BomVersion
WHERE
products.active = 1
order by products.productid, products.type,comp.productid
To combine them you could do the following.
SELECT b.*
FROM
(SELECT Products.ProductID FROM Products INNER JOIN ...) AS a
INNER JOIN
(SELECT Products.ProductID, Products.productdescription, Boms.Type As Type, ...) AS b
ON a.ProductID = b.ProductID

How to correctly join table which may return more than one row

I have a table Items which have the following columns:
ItemId || AdminUserID || ItemName
And I try to join it with ItemAttributes:
ItemAttributeId || ItemId || AttributeValue
where one ItemId can have several ItemAttributeId values assigned to it.
I created procedure to retrieve item values from two tables:
SELECT
i.ItemID,
i.AdminUserID,
i.ItemName,
attr1.AttributeValue as IsForEmailRobotProcessingValue,
attr2.AttributeValue as RobotScheduledHoursValue -- HERE IS THE PROBLEM
FROM [dbo].[Items] i WITH (NOLOCK)
LEFT JOIN [dbo].ItemAttributes attr1 WITH(NOLOCK)
ON attr1.ItemID = i.ItemID and attr1.ItemAttributeID = 1
LEFT JOIN [dbo].ItemAttributes attr2 WITH(NOLOCK)
ON attr2.ItemID = i.ItemID and attr2.ItemAttributeID = 2
WHERE ((attr1.AttributeValue IS NOT NULL AND attr1.AttributeValue = 'true') OR
#OnlyForEmailRobotProcessing = 0)
ORDER BY ItemName
What I don't like here is that I LEFT JOIN two times the same table and created different aliases for each join according to the same ItemId. Is there any better way to LEFT JOIN only one time and created two different aliases for each ItemAttributeId? Thanks!
Try this:
SELECT
i.ItemID,
i.AdminUserID,
i.ItemName,
attr1.AttributeValue1 as IsForEmailRobotProcessingValue,
attr1.AttributeValue2 as RobotScheduledHoursValue
FROM [dbo].[Items] i WITH (NOLOCK)
LEFT JOIN
(select ItemId, (select AttributeValue
from [dbo].ItemAttributes a
where a.ItemId = b.ItemId and a.ItemAttributeID = 1) as AttributeValue1,
(select AttributeValue
from [dbo].ItemAttributes c
where c.ItemId = b.ItemId and c.ItemAttributeID = 2) as AttributeValue2
from [dbo].ItemAttributes b WITH(NOLOCK)
where b.ItemId = i.ItemID and b.ItemAttributeID in (1,2)
) attr1 on i.ItemId = attr1.ItemId
WHERE ((attr1.AttributeValue IS NOT NULL AND attr1.AttributeValue = 'true') OR
#OnlyForEmailRobotProcessing = 0)
ORDER BY ItemName

"Error near from" in UNION query

I'm getting an error "error near FROM" in SQLite, however I couldn't find any faults in this query. What am I doing wrong?
Select
tbltrans2_temp.itemcode,
tbltrans2_temp.itemname,
Sum(tbltrans2_temp.qty) qty
From
tbltrans_temp Inner Join
tbltrans2_temp On tbltrans2_temp.transID = tbltrans_temp.transid
where
tbltrans_temp.saleDate='11/07/2013'
Group By
tbltrans2_temp.itemcode
UNION
Select
tbltrans2.itemcode,
tbltrans2.itemname,
Sum(tbltrans2.qty) qty,
From
tbltrans Inner Join
tbltrans2 On tbltrans2.transid = tbltrans.transid
where
tbltrans.saleDate='11/07/2013'
Group By
tbltrans2.itemcode
There is an extra , before the second FROM remove it:
Select
tbltrans2_temp.itemcode,
tbltrans2_temp.itemname,
Sum(tbltrans2_temp.qty) qty
From
tbltrans_temp Inner Join
tbltrans2_temp On tbltrans2_temp.transID = tbltrans_temp.transid
where
tbltrans_temp.saleDate='11/07/2013'
Group By
tbltrans2_temp.itemcode
UNION
Select
tbltrans2.itemcode,
tbltrans2.itemname,
Sum(tbltrans2.qty) qty, <<<<------------------- This
From
tbltrans Inner Join
tbltrans2 On tbltrans2.transid = tbltrans.transid
where
tbltrans.saleDate='11/07/2013'
Group By
tbltrans2.itemcode
Update
To get the sum of qty from both the table, put that query in a subquery and sum it in the outer one, you can also omit the sum in the inner query and only do it in the outer one:
SELECT
itemcode,
itemname,
SUM(qty) TotalQty
FROM
(
Select
tbltrans2_temp.itemcode,
tbltrans2_temp.itemname,
Sum(tbltrans2_temp.qty) qty
From
tbltrans_temp Inner Join
tbltrans2_temp On tbltrans2_temp.transID = tbltrans_temp.transid
where
tbltrans_temp.saleDate='11/07/2013'
Group By
tbltrans2_temp.itemcode
UNION
Select
tbltrans2.itemcode,
tbltrans2.itemname,
Sum(tbltrans2.qty) qty
From
tbltrans Inner Join
tbltrans2 On tbltrans2.transid = tbltrans.transid
where
tbltrans.saleDate='11/07/2013'
Group By
tbltrans2.itemcode
) t
GROUP BY itemcode, itemname;

Count from another table with join

How can I Count the Lending comments for each lending (the comments is on another table called "LendingComments" with a reference Column called "LendingId" ?
SELECT LendingStatus.Status, Products.Productname, Products.Serial_number, Deposits.Amount, Lendings.DeliveryDate, Lendings.Id AS LendingId, Products.Id AS ProductId FROM Lendings
LEFT JOIN Products ON Lendings.ProductId = Products.Id
LEFT JOIN LendingStatus ON Lendings.StatusId = LendingStatus.Id
LEFT JOIN Deposits ON Lendings.DepositId = Deposits.Id
WHERE PersonId = 561 ORDER BY DeliveryDate DESC
Maby like this (if I understand the question well enough)
SELECT
LendingStatus.Status, Products.Productname, Products.Serial_number,Deposits.Amount, Lendings.DeliveryDate, Lendings.Id AS LendingId, Products.Id AS ProductId, LendingComments.NumLendingComments
FROM Lendings
LEFT JOIN Products ON Lendings.ProductId = Products.Id
LEFT JOIN LendingStatus ON Lendings.StatusId = LendingStatus.Id
LEFT JOIN Deposits ON Lendings.DepositId = Deposits.Id
OUTER APPLY
(
SELECT
COUNT(*) AS NumLendingComments
FROM
LendingComments PL
WHERE
PL.LendingID = Lendings.LendingID
) AS LendingComments WHERE Personid = 561 ORDER BY DeliveryDate desc
Maybe this helps:
SELECT CommentCount = Sum(lc.comments)
OVER (
partition BY lc.id),
lendingstatus.status,
products.productname,
products.serial_number,
deposits.amount,
lendings.deliverydate,
lendings.id AS LendingId,
products.id AS ProductId
FROM lendings
LEFT JOIN products
ON lendings.productid = products.id
LEFT JOIN lendingstatus
ON lendings.statusid = lendingstatus.id
LEFT JOIN deposits
ON lendings.depositid = deposits.id
LEFT JOIN LendingComments lc
ON lc.LendingId = lendings.Lendings.Id
WHERE personid = 561
ORDER BY deliverydate DESC
However, you have not shown the PersonLendings table, have you?
Try this one -
SELECT ls.status
, p.Productname
, p.Serial_number
, d.AMOUNT
, l.DeliveryDate
, l.Id AS LendingId
, p.Id AS ProductId
, pl.cnt
FROM dbo.Lendings l
LEFT JOIN (
SELECT pl.LendingId, cnt = COUNT(pl.LendingComments)
FROM dbo.PersonLendings pl
GROUP BY pl.LendingId
) pl ON pl.LendingId = l.LendingId
LEFT JOIN dbo.Products p ON l.ProductId = p.Id
LEFT JOIN dbo.LendingStatus ls ON l.StatusId = ls.Id
LEFT JOIN dbo.Deposits d ON l.DepositId = d.Id
WHERE PersonID = 561
ORDER BY l.DeliveryDate DESC