I want a query to extract the table data from SQL Server - sql

Items table:
ItemNo, Description, BaseUnitOfMeasure, UnitPrice
-------------------------------------------------
1 Prod1 pc 200
2 prod2 pc 150
3 prod3 pc 120
ItemsLedger table:
ItemNo, Quantity
----------------
1 400
1 -20
1 -5
Above are my two tables and I want to extract the data in a format below
ItemNo, Description, BaseUnitOfMeasure, UnitPrice, Quantity
------------------------------------------------------------
1 prod1 pc 200 375
I tried this query but didn't work
SELECT
item.[No_],
item.[Description],
item.[Base Unit of Measure],
item.[Unit Price],
SUM(ledger.[Quantity])
FROM
items AS item
LEFT JOIN
ItemLedger AS ledger ON item.No_ = ledger.[Item No_]
GROUP BY
item.No_
but it didn't work. Ignore typos and table names etc.

In SQL Server, you need to include all non-aggregated columns in the GROUP BY:
SELECT i.[No_], i.[Description], i.[Base Unit of Measure], i.[Unit Price],
Sum(il.[Quantity])
FROM items i LEFT JOIN
ItemLedger as il
ON i.No_ = l.[Item No_]
GROUP BY i.[No_], i.[Description], i.[Base Unit of Measure], i.[Unit Price]

Related

Find the products contributing to the 50% of the total sales using SQL SUM window Function

There are two Tables - orders and item_line
orders
order_id
created_at
total_amount
123
2022-11-11 13:40:50
450.00
124
2022-10-30 00:40:50
1500.00
item_line
order_id
product_id
product_name
quantity
unit_price
123
a1b
milo
4
100.00
123
c2d
coke
5
10.00
124
c2d
coke
150
10.00
The question is:
Find the products contributing to the 50% of the total sales.
My take on this is -
SELECT i.product_name,SUM(o.total_amount)AS 'Net Sales'
FROM item_line i
JOIN orders o on o.order_id = i.order_id
GROUP BY i.product_name
HAVING SUM(o.total_amount) = (SUM(o.total_amount)*0.5);
But this is not correct. SUM windows functions need to be used, but how?
Try the following, explanation is within the query comments:
-- find the the total sales for each product
WITH product_sales AS
(
SELECT product_id, product_name,
SUM(quantity * unit_price) AS product_tot_sales
FROM item_line
GROUP BY product_id, product_name
),
-- find the running sales percentage for each product starting from porduct with highest sales value
running_percentage AS
(
SELECT product_id, product_name, product_tot_sales,
SUM(product_tot_sales) OVER (ORDER BY product_tot_sales DESC) /
SUM(product_tot_sales) OVER () AS running_sales_percentage,
SUM(product_tot_sales) OVER () AS tot_sales
FROM product_sales
)
-- select products that have a running sales percentage less than the min(running_sales_percentage) where running_sales_percentage >= 0.5
-- this will select all of products that contributes of 0.5 of the total sales
SELECT product_id, product_name, product_tot_sales,
tot_sales,
running_sales_percentage
FROM running_percentage
WHERE running_sales_percentage <=
(
SELECT MIN(running_sales_percentage)
FROM running_percentage
WHERE running_sales_percentage >= 0.5
)
You don't need a join with orders table, all data you need is existed in the item_line table.
See demo.

SQL - Return group of records from different tables not including specific row

I am new at programming and SQL, so sorry if I do not include enough info.
[I have these 2 tables that are linked by an OrderID. Table1 includes OrderIDs and customer information such as FirstName, LastName, and Address. Table2 includes OrderIDs and order details such as ItemName, Price, and Quantity.
Each OrderID in Table2 might have multiple ItemName entries with the same OrderID.]1
CustInfo
OrderID FirstName LastName Address
1 Bob Pratt 123
2 Jane Doe 456
3 John Smith 789
4 Barbara Walters 147
Orders
OrderID ItemName Price Quantity
1 Milk 4.00 1
1 Eggs 5.00 2
2 Cheese 5.00 1
2 Bread 5.00 1
3 Milk 4.00 2
4 Yogurt 5.00 2
I'm trying to make a query that will send back a list of every Order, listing the OrderID and ItemName among other info, as long as the order doesn't include a specific type of item (which would be in ItemName). So if an OrderID contains 2 ItemName, one of which is the one I do not want, the entire order (OrderID) should not show up in my result.
For example, based off the img included, if I wanted to show all orders as long as they do not have Milk as an ItemName, the result should only show OrderID 2 and 4.
2 Cheese 5.00 1
2 Bread 5.00 1
4 Yogurt 5.00 2
This is what I have tried but this would return OrderIDs even though Milk is technically part of that OrderID.
SELECT OrderID, FirstName, LastName, ItemName, Price, Quantity
FROM CustInfo
JOIN Orders
ON CustInfo.OrderID = Orders.OrderID
WHERE ItemName != 'Milk'
Can you help?
select o.OrderID, o.ItemName, c.FirstName, c.LastName -- include other fields if needed
from Orders o
left join CustInfo c on o.OrderID = c.OrderID
where o.OrderID not in (
select OrderID from Orders where ItemName = 'Milk'
)
If you want the whole order to not show up, rather than just individual rows, you can use WHERE NOT EXISTS:
SELECT o.OrderID, d.ItemName, d.Price, d.Quantity
FROM Orders o
JOIN OrderDetails d ON o.OrderID=d.OrderID
WHERE NOT EXISTS
(
SELECT * FROM OrderDetails d2
WHERE o.OrderID=d2.OrderID
AND d.ItemName = 'Milk'
)
SELECT T1.OrderID, T1.FirstName, T1.LastName, T1.Address, T2.OrderID, T2.ItemName, T2.Price, T2.Quantity
FROM Table2 as T2
LEFT JOIN Table1 as T1 ON T1.OrderID = T2.OrderID
WHERE T2.OrderID <> (SELECT OrderID FROM Table2 WHERE ItemName='Milk');

Sum between 3 linked tables SQL Server

I am trying to pull a sum from linked table.
Order:
OrderID LocationID OrderDate
100 1 1/1/2000
200 2 1/2/2000
OrderedItems:
ID OrderID ItemID
1 100 1
2 200 2
3 200 2
4 100 3
OrderItem:
ItemID ItemName Cost
1 Mobile1 100.00
2 Mobile2 200.00
3 Mobile3 300.00
The Order table is effectively a group of OrderedItems. Each row in OrderedItems links back to OrderItem via the ItemID.
I am trying to add a column to the below query for order total.
Order Number Location Date Ordered Order Total
-------------------------------------------------------
100 Sydney 1/1/2000 400
200 Brisbane 1/2/2000 400
The current query I have is:
SELECT
Order.OrderID AS [Order Number],
OL.Name AS [Location],
Order.OrderDate AS [Date Ordered]
FROM
Order
LEFT JOIN
Office_Locations AS OL ON OL.id = Order.LocationID
I have tried to follow this link however I am needing to link through 3 tables for the values to add.
Any hep would be great!
You're not finding a sum from three tables. You're finding a sum from one table: the OrderItem table. The only trick is getting the JOIN and GROUP BY expressions done correctly to make that column available.
SELECT o.OrderID As [Order Number], l.Name As Location
, o.OrderDate As [Date Ordered], SUM(i.Cost) As [Order Total]
FROM [Order] o
INNER JOIN Office_Locations l on l.id = o.LocationID
INNER JOIN OrderedItems oi on oi.OrderID = o.OrderID
INNER JOIN OrderItem i ON i.ItemID = oi.ItemID
GROUP BY o.OrderID, l.Name, o.OrderDate
SQLFIDDLE
You need to use SUM to get the total Cost:
SQL Fiddle
SELECT
[Order Number] = o.OrderID,
Location = ol.Name,
[Date Ordered] = o.OrderDate,
[Order Total] = SUM(i.Cost)
FROM [Order] o
INNER JOIN OrderedItems oi
ON oi.OrderId = o.OrderId
INNER JOIN OrderItem i
ON i.ItemID = oi.ItemID
LEFT JOIN Office_Locations ol
ON ol.id = o.LocationID
GROUP BY
o.OrderID, o.OrderDate, ol.Name
As commented by Joel Coehoorn, it's more normal to have a quantity field in the OrderedItems table than to repeat them. Following his advise, your OrderedItems table should be:
ID OrderID ItemID Quantity
1 100 1 1
2 200 2 2
3 100 3 1
Additional Notes:
Use meaningful aliases to improve readability.
Refrain from using reserved words as your object names i.e. Order could be renamed as OrderHeader.

Get stock from Purchased and Sold Products QTY

I have been working on Client project. I need to get stock from Purchased product QTY and Sold QTY.
Here my SQL
SELECT DISTINCTROW tbl_itemmaster.product_code,tbl_itemmaster.unittype,tbl_itemmaster.color,SUM(tbl_purchasedetails.qty),SUM(tbl_saledetails.qty),(SUM(tbl_purchasedetails.qty)-SUM(tbl_saledetails.qty))
FROM (tbl_itemmaster LEFT JOIN tbl_saledetails ON tbl_itemmaster.[product_code] = tbl_saledetails.[product_code])
LEFT JOIN tbl_purchasedetails ON tbl_itemmaster.[product_code]=tbl_purchasedetails.[product_code] GROUP BY tbl_itemmaster.product_code,tbl_itemmaster.unittype,tbl_itemmaster.color
Below is the result of sql
-----------------------------------------------------------------
Product Code Unit Type Color Purchase QTY Sold QTY Stock
-----------------------------------------------------------------
1001 KiloGram Red 500
500 Kilogram White 1033 300 733
570 Kilogram Black
600 Kilogram Pink
9005 Kilogram Magenta 800.5
900 Kilogram Green
-----------------------------------------------------------------
Product code 500 has three times purchase entry i.e. 500+400+133 = 1033 Purchased Qty
Product code 500 has only ONE time sale entry i.e. 100 = 100 Sold Qty
Product code 500 suppose to has 933 Stock Qty
BUT why I getting 300 in sold qty ?
Where my query is lacking?
PLEASE HELP !!!
You are getting cartesian products, because products have multiple sales and purchases.
The solution is to do the aggregation before the join:
SELECT im.product_code, im.unittype, im.color,
pd purchaseqty, sd.salesqty),
(purchaseqty - salesqty)
FROM (tbl_itemmaster as im LEFT JOIN
(SELECT product_code, SUM(qty) as salesqty
FROM tbl_saledetails
GROUP BY product_code
) as sd
ON im.[product_code] = sd.[product_code]
) LEFT JOIN
(SELECT product_code, SUM(qty) as purchaseqty
FROM tbl_purchasedetails
GROUP BY product_code
) as pd
ON im.[product_code] = pd.[product_code];

Select data from multiple table where there may not necessarily be a match between some tables

Trying to return the rest of the matches from other tables even if one of two table doesn't have a match. Best I can explain this, sorry.
Given the following tables
customers table
customerid firstname lastname EmailAddress etc...
1 Tom Smith tsmith#abc.com
2 Mike Adams mikea#abc.com
etc...
orders table
orderid customerid orderdate etc..
1 1 11/8/2007 8:53:00 AM
2 1 11/8/2007 8:53:00 AM
3 2 11/8/2007 8:53:00 AM
4 3 11/8/2007 8:53:00 AM
5 4 11/8/2007 8:53:00 AM
6 3 11/8/2007 8:53:00 AM
7 5 11/8/2007 8:53:00 AM
8 3 11/8/2007 8:53:00 AM
orderdetails table
orderid productcode productname productprice quantity etc...
1 widget1 widget 1 5.00 5
2 widget2 widget 2 6.00 3
3 widget3 widget 3 7.00 2
etc...
product table
vendor_partno productcode productprice saleprice
wig1 widget1 10.00 7.50
wig3 widget3 8.00
etc...
As you can see in the product table that widget2 product is no longer in the inventory. I am trying to select all product previously purchased by a specific customer based on there e-mail address and customer id. I need to display all products they have purchased even if it is not longer available in the product table.
The following query only shows those that are still in the products table.
What I want is to return all info shown in the select and if corresponding product info in the product table doesn't exist then just return the data that does exist.
SELECT CONVERT(VARCHAR(10), orders.orderdate, 101) AS OrderDate,
orderdetails.orderid,
orders.customerid,
customers.emailaddress,
orderdetails.productcode AS orig_product_code,
orderdetails.productname,
orderdetails.productprice,
orderdetails.quantity,
products_joined.vendor_partno,
products_joined.productcode,
products_joined.productprice AS current_reg_price,
products_joined.saleprice AS current_sale_price
FROM orders,
customers,
orderdetails,
products_joined
WITH (NOLOCK)
WHERE
orders.orderid = orderdetails.orderid
AND customers.customerid = orders.customerid
AND orderdetails.productcode = products_joined.productcode
AND customers.emailaddress = 'tsmith#abc.com'
AND customers.customerid = '1'
ORDER BY orders.orderid DESC
Right now what is returned is
orderdate orderid customerid emailaddress orig_product_code product name product price quantity vendor_partno productcode current_reg_price current_sale_price
11/8/2007 1 1 tsmith#abc.com widget1 widget 1 5.00 5 wig1 widget1 10.00 7.50
What I would like returned is
orderdate orderid customerid emailaddress orig_product_code product name product price quantity vendor_partno productcode current_reg_price current_sale_price
11/08/2007 1 1 tsmith#abc.com widget1 widget 1 5.00 5 wig1 widget1 10.00 7.50
11/08/2007 2 1 tsmith#abc.com widget2 widget 2 6.00 3
Obviously the reason for this is
orderdetails.productcode = products_joined.productcode
but i am not sure how to get fix this.
Any help would be appreciated.
I think you just need an outer join with the products_joined table like below.
Also it would be a good idea to use modern JOIN syntax; ie. put all join conditions into the JOIN clause rather than the WHERE clause, like so:
SELECT CONVERT(VARCHAR(10), orders.orderdate, 101) AS OrderDate,
orderdetails.orderid,
orders.customerid,
customers.emailaddress,
orderdetails.productcode AS orig_product_code,
orderdetails.productname,
orderdetails.productprice,
orderdetails.quantity,
products_joined.vendor_partno,
products_joined.productcode,
products_joined.productprice AS current_reg_price,
products_joined.saleprice AS current_sale_price
FROM orders
join customers
on customers.customerid = orders.customerid
join orderdetails
on orders.orderid = orderdetails.orderid
left join products_joined
on orderdetails.productcode = products_joined.productcode
WHERE customers.emailaddress = 'tsmith#abc.com'
AND customers.customerid = '1'
ORDER BY orders.orderid DESC