SQL Using Multiply 3 Times with different ID's - sql

I have tables called Products and ProductsDetails. I want to get something like the price of an order. So let's say I want 5 pairs of "Headphonesv1" ( Comparing with not ID but name, since name could change ), 2 packs of "GumOrbit" and 7 packs of "crisps". Pair of headphonesv1 costs 10$, gum 1$ and crisps 2$. So the answer that I should get is bill ID, Bill date, and TotalCost which is = 66. My question is how do I make multiple calculations? The code that I've been trying with one at least but I get syntax error:
SELECT Products.billID, Products.Date, (ProductsDetails.Price * 5 WHERE ProductsDetails.name LIKE 'Headphonesv1')
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
Also have tried inserting SELECT inside () but then the values that I get are wrong and creating one more inner join inside doesn't seem promising

I think if you just want to see that total cost for multiple items you can use a aggregate and case expression to get the SUM.
SELECT Products.billID,
Products.Date,
SUM(CASE WHEN ProductsDetails.name LIKE 'Headphonesv1' THEN ProductsDetails.Price * 5
WHEN ProductsDetails.name LIKE 'GumOrbit' THEN ProductsDetails.Price * 2
WHEN ProductsDetails.name LIKE 'crisps' THEN ProductsDetails.Price * 7
END) TotalCost
FROM Products
INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
GROUP BY Products.billID,
Products.Date
this seems very hard coded to serve much use though

Your previous code has a few synax erros. you are closing your parenthesis in the wrong location, and the FROM ... clause should be before the WHERE ... clause. Change your code to this:
SELECT Products.billID, Products.Date, (ProductsDetails.Price * 5)
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
WHERE ProductsDetails.name LIKE 'Headphonesv1'
and let me know if it works now.
Edited:
The OP requested how to obtain that information for more than one Product. In that case you could switch the statement to:
SELECT SUM(Cost)
FROM (
SELECT Products.billID, Products.Date,
(ProductsDetails.Price *
(CASE WHEN ProductsDetails.name='Headphonesv1' THEN 5 ELSE
CASE WHEN ProductsDetails.name='GumOrbit' THEN 7 ELSE 0 END
END)
) AS Cost
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
WHERE (ProductsDetails.name = 'Headphonesv1') OR (ProductsDetails.name = 'GumOrbit')
)
And you can continue to add more products.

You probably have another two tables: cart(cartID int/*,more info*/) and cartItems(cartID int /*FK*/, item varchar(50),qty int) where you add something. Finally,
select sum(pd.price * ci.qty) tot
FROM Products p
INNER JOIN ProductsDetails pd ON p.billdID = pd.billID
inner join cartItems ci on ci.item = pd.name
inner join cart c on c.cartID = ci.cartID
where c.cartID = 123456

Related

MS SQL count values for per row for per id

I'm trying to count incident types per depot. My current query returns the following result set:
I then apply a count query on this set which looks like this:
select middleList.DepotName as depot,
count(middleList.NearMiss) as NearMiss,
count(middleList.Theft) as Theft,
count(middleList.Security) as Security,
count(middleList.LostTimeDisablingInjury) as LostTimeDisablingInjury,
count(middleList.Fire) as Fire,
count(middleList.OccupationalIllness) as OccupationalIllness,
count(middleList.VehicleAccident) as LostTimeDisablingInjury,
count(middleList.Spliiage) as Fire,
count(middleList.PropertyDamage) as OccupationalIllness,
count(middleList.NonConformance) as NonConformance,
count(middleList.Other) as Other
from
(SELECT dbo.IncidentTypes.NearMiss, dbo.IncidentTypes.Theft,
dbo.IncidentTypes.Security, dbo.IncidentTypes.LostTimeDisablingInjury,
dbo.IncidentTypes.Fire, dbo.IncidentTypes.OccupationalIllness,
dbo.IncidentTypes.VehicleAccident, dbo.IncidentTypes.Spliiage,
dbo.IncidentTypes.PropertyDamage, dbo.IncidentTypes.NonConformance,
dbo.IncidentTypes.Other, dbo.Incidents.IncidentTitle, dbo.Depots.DepotName,
dbo.Incidents.IncidentNumber
FROM dbo.Departments INNER JOIN
dbo.Depots ON dbo.Departments.DepotId = dbo.Depots.DepotId
INNER JOIN
dbo.Employees ON dbo.Departments.DepartmentId =
dbo.Employees.DepartmentId INNER JOIN
dbo.IncidentTypes INNER JOIN
dbo.Incidents ON dbo.IncidentTypes.IncidentTypeId =
dbo.Incidents.IncidentTypeId ON dbo.Employees.EmployeeId =
dbo.Incidents.EmployeeId_EmployeeInvolv
Where Incidents.DateCreated = (SELECT MAX (i2.DateCreated) FROM
Incidents as i2 WHERE Incidents.IncidentNumber = i2.IncidentNumber)) as
middleList
group by middleList.DepotName
Which return the following incorrect results:
Please help.
Okay so I found the problem.
It seems like the rows are being counted and not the actual values, thus adding this to the count insured that they were being counted properly:
count(case when middleList.NearMiss <> '0' then 0 end ) as NearMiss
End result being:

Display only result > 2

I face a problem with the result on my script.
My formula for MARGIN is ((plnamt-(ibhexc/ibhand))/plnamt)*100.
I want to display only result > 2. How to do this? Please help.
This my script:
select
a.plnitm,a.plnstr,max(a.plncdt),max(a.plnndt),max(a.plnamt),max(a.plnevt),b.idept,c.ibhand,c.ibhexc,
decimal((c.ibhexc/c.ibhand),12,4) as AVG_COST,
decimal(((((max(a.plnamt)-(c.ibhexc/c.ibhand))/(max(a.plnamt))))*100),12,4) as MARGIN
from prcpln a
inner join invmst b on a.plnitm = b.inumbr
inner join invbal c on a.plnitm = c.inumbr and a.plnstr = c.istore and c.ibhand <> 0
where a.plnstr = ''14006''
group by a.plnitm,a.plnstr,b.idept,c.ibhand,c.ibhexc
order by a.plnitm
Simplistically, for situations like this, you can take your query and put it inside a cte:
WITH q AS (
select
a.plnitm,a.plnstr,max(a.plncdt),max(a.plnndt),max(a.plnamt),max(a.plnevt),b.idept,c.ibhand,c.ibhexc,
decimal((c.ibhexc/c.ibhand),12,4) as AVG_COST,
decimal(((((max(a.plnamt)-(c.ibhexc/c.ibhand))/(max(a.plnamt))))*100),12,4) as MARGIN
from prcpln a
inner join invmst b on a.plnitm = b.inumbr
inner join invbal c on a.plnitm = c.inumbr and a.plnstr = c.istore and c.ibhand <> 0
where a.plnstr = ''14006''
group by a.plnitm,a.plnstr,b.idept,c.ibhand,c.ibhexc
)
SELECT * FROM q WHERE margin > 2
ORDER BY q.plnitm
This is similar to the advice to use HAVING - a HAVING is a "where clause that is done after a GROUP BY"
A cte is a way of taking some calculated block of data and giving it an alias that can be used just like a table. I wanted to answer this way to point out to you that queries don't have to be formed purely from tables; tables are just blocks of data (with a name), and the output from a select is also "just a block of data" that can be given a name (by use of a cte or subquery) and then used just like a table is

Simple sql query with multiple tables

I'm trying to write a simple query but the output is not correct:
Herer my code:
SELECT oc_order_product.order_id AS ordernumber, oc_order_product.quantity,
oc_order_product.model, oc_order_product.name,
oc_order.shipping_company, oc_order.shipping_firstname,
oc_order.shipping_lastname, oc_order.shipping_city, oc_product.location
FROM oc_order_product,
oc_order,
oc_product
WHERE oc_order.order_id = oc_order_product.order_id
AND oc_order.order_status_id = 1
AND oc_product.location = 1
ORDER BY ordernumber, oc_order_product.model
The output is a list of all products with the oc_order.order_status_id = 1 but the second AND (oc_product.location = 1) is not applied. What is wrong? I don't work with JOIN because I don't understand it really good.
Now using modern, explicit JOIN:
SELECT oc_order_product.order_id AS ordernumber, oc_order_product.quantity,
oc_order_product.model, oc_order_product.name,
oc_order.shipping_company, oc_order.shipping_firstname,
oc_order.shipping_lastname, oc_order.shipping_city, oc_product.location
FROM oc_order_product
INNER JOIN oc_order ON oc_order.order_id = oc_order_product.order_id
INNER JOIN oc_product ON oc_product.id = oc_order_product.product_id
WHERE oc_order.order_status_id = 1
AND oc_product.location = 1
ORDER BY ordernumber, oc_order_product.model
That last join
INNER JOIN oc_product ON oc_product.id = oc_order_product.product_id
is just a guess, since I don't know which columns to use!
jarlh is guessing that oc_product.id = oc_order_product.product_id.
I'm going to guess that your data element names are consistently and uniquely named throughout your schema and therefore suggest you use ultra-modern NATURAL JOIN:
SELECT order_id AS ordernumber, quantity,
model, name, shipping_company, shipping_firstname,
shipping_lastname, shipping_city, location
FROM oc_order_product
NATURAL JOIN oc_order
NATURAL JOIN oc_product
WHERE order_status_id = 1
AND location = 1
ORDER
BY ordernumber, model;
...not betting the farm on it, though.

SQL Display Distinct records and include a field if certain data is found

What I'm trying to accomplish is display distinct data but also display a field on each row if a particular row has a certain data.
The thing thats confusing me is the fact that I still need it to be distinct and if I attempt to do another join i get more rows..
I just wish to keep the same results i'm retrieving but with an additional column that tells me - This equipment (row) needs repairs because at least one of its properties stated so... Hope this makes sense, not sure if I'm explaining myself clearly here.
The Main Table (Inspection Table)
In the above table, Notice FK_Sequence Each entry has around 17 which the user is required to answer OK or REPAIR (this is the FK_Status)
My current Query is the following and results just an Employee and the equipment they worked on.
SELECT DISTINCT
a.EnteredDate,
bb.EmployeeId,
bb.EmployeeName,
dd.EquipmentId,
dd.EquipmentName
FROM dbo.PIT_Inspection a
INNER JOIN dbo.EmployeeName bb
ON a.FK_EmployeeName = bb.PK_EmployeeName
INNER JOIN dbo.EquipmentName dd
ON a.FK_EquipmentName = dd.PK_EquipmentName
Results for above query:
But then here is where my question comes in. Notice the Main Table - FK_Status of 2 on Line 19.. I would like to detect this and for this particular Employee Display Repair in an additional column in the table above named StatusName.
You can do this by using GROUP BY instead of DISTINCT, then you can use a conditional count to see how many rows have a status of 2, if it is more than none then display REPAIR
SELECT a.EnteredDate,
bb.EmployeeId,
bb.EmployeeName,
dd.EquipmentId,
dd.EquipmentName,
StatusName = CASE WHEN COUNT(CASE WHEN a.FK_Status = 2 THEN 1 END) > 0
THEN 'REPAIR'
ELSE ''
END
FROM dbo.PIT_Inspection a
INNER JOIN dbo.EmployeeName bb
ON a.FK_EmployeeName = bb.PK_EmployeeName
INNER JOIN dbo.EquipmentName dd
ON a.FK_EquipmentName = dd.PK_EquipmentName
GROUP BY a.EnteredDate, bb.EmployeeId, bb.EmployeeName, dd.EquipmentId, dd.EquipmentName;
Try this:
SELECT
a.EnteredDate,
bb.EmployeeId,
bb.EmployeeName,
dd.EquipmentId,
dd.EquipmentName,
CASE WHEN SUM(CASE FK_Status WHEN 2 THEN 1 ELSE 0 END) > 0
THEN 'Repair' ELSE 'OK' END AS StatusName
FROM dbo.PIT_Inspection a
INNER JOIN dbo.EmployeeName bb
ON a.FK_EmployeeName = bb.PK_EmployeeName
INNER JOIN dbo.EquipmentName dd
ON a.FK_EquipmentName = dd.PK_EquipmentName
GROUP BY
a.EnteredDate,
bb.EmployeeId,
bb.EmployeeName,
dd.EquipmentId,
dd.EquipmentName
Have the query with the distinct as a sub query, then join to get the "additional information". Something along the lines of:
SELECT (your orig fields, but take from inspection where you took from a)
FROM
(SELECT DISTINCT a.FK_EmployeeName, a.EnteredDate, FK_EquipmentName
FROM dbo.PIT_Inspection a) inspection
INNER JOIN dbo.EmployeeName bb
ON inspection.FK_EmployeeName = bb.PK_EmployeeName
INNER JOIN dbo.EquipmentName dd
ON inspection.FK_EquipmentName = dd.PK_EquipmentName

SQL Query returning multiple Duplicate Results

scenario : I have Three Tables(Prisoners,AddPaymentTransaction,WithdrawPaymentTransation)
Date in Tables : i have 1 row of prisoner with PrisonerID=5 and two rows in both other table,
i have wrote query to return there data if any prisoner have add some payment in there account or with draw any payment from there payment on same day or on different dates etc.
here is my query :
select at.PrisonerID ,at.Amount as AAmount,at.Date as ADate,wt.Amount as WAmount,wt.Date as WDate
from Prisoners p, AddPaymentTransaction at,WithdrawPaymentTransation wt
where p.PrisonerID=at.PrisonerID and p.PrisonerID=wt.PrisonerID and at.PrisonerID=wt.PrisonerID and at.PrisonerID=5
but it gives me 4 rows, 9 rows when i have 3 rows of data in each Table etc.
i want rows of data with out duplicate. any suggestions or help will be highly appreciated.
It looks like at.PrisonerID = wt.PrisonerID in your query might be what is causing all of the duplicates. I am guessing AddPaymentTransaction and WithdrawPaymentTransation should not be linked together. So, how about the following:
SELECT at.PrisonerID, at.Amount as AAmount, at.Date as ADate,
wt.Amount as WAmount, wt.Date as WDate
FROM Prisoners p
INNER JOIN AddPaymentTransaction at p.PrisonerID = at.PrisonerID
INNER JOIN WithdrawPaymentTransation wt ON p.PrisonerID = wt.PrisonerID
WHERE at.PrisonerID = 5
but this probably isn't going to give you exactly what you are looking for either. So maybe something like the following:
SELECT * FROM
(
SELECT p.PrisonerID, 'AddPayment' AS Type,
apt.Amount as TransAmount, apt.Date AS TransDate
FROM Prisoners p
INNER JOIN AddPaymentTransaction apt ON p.PrisonerID = apt.PrisonerID
WHERE apt.PrisonerID = 5
UNION
SELECT p.PrisonerID, 'WithdrawPayment' AS Type,
wt.Amount as TransAmount, wt.Date as TransDate
FROM Prisoners p
INNER JOIN WithdrawPaymentTransation wt ON p.PrisonerID = wt.PrisonerID
WHERE wt.PrisonerID = 5
) AS mq
ORDER BY mq.TransDate DESC