Sql Inner Join among 2 tables summing the qty field multiple times - sql

I have two tables , A and B
Table A contains:
OrderNo | StyleNo | Qty
O-20 | S-15 | 20
O-20 | S-18 | 40
O-25 | S-19 | 50
Table B contains:
OrderNo | StyleNo | Ship Qty
O-20 | S-15 | 5
O-20 | S-18 | 30
O-20 | S-15 | 12
O-20 | S-18 | 6
Result Requires
OrderNo | StyleNo | Qty | Ship Qty
O-20 | S-15 | 20 | 17
O-20 | S-18 | 40 | 36
O-25 | S-19 | 50 | 0
The following query is not working
select
B.Orderno, B.StyleNo, sum(A.Qty), sum(B.QtyShip)
from
A
inner join
B on A.OrderNo = B.OrderNo and A.StyleNo = B.StyleNo
group by
B.OrderNo, B.StyleNo

The issue you're having is that it's summing the qty field multiple times. Move the sums to subqueries and use a join on those:
select a.orderno, a.styleno, a.qty, b.qtyship
from (
select orderno, styleno, sum(qty) qty
from a
group by orderno, styleno
) a
join (
select orderno, styleno, sum(qtyship) qtyship
from b
group by orderno, styleno
) b on a.orderno = b.orderno and a.styleno = b.styleno
SQL Fiddle Demo

Related

Select highest value from joined table

I need to select a distinct row based on a value from a joined table in SQL Server.
Table Orderlines:
| order_id | product_id|
|------------|------------|
| 1234 | 11 |
| 1234 | 22 |
| 1234 | 33 |
| 1234 | 44 |
| 1234 | 55 |
| 2222 | 66 |
| 2222 | 77 |
Table Products:
| product_id | deliverytime|
|------------|--------------|
| 11 | 2 |
| 22 | 3 |
| 33 | 5 |
| 44 | 2 |
| 55 | 1 |
| 66 | 4 |
| 77 | 1 |
Result I am looking for:
| order_id | product_id| deliverytime|
|------------|------------|--------------|
| 1234 | 33 | 5 |
| 2222 | 66 | 4 |
Thanks in advance
We can RANK by deliverytime DESC in a CTE and then only take RANK 1 which is the highest value.
WITH CTE AS
(SELECT
o.product_id,
o.order_id
p.deliverytime,
RANK() OVER (PARTITION BY order_id
ORDER BY deliverytime DESC) rn
FROM Orderline o
JOIN Products p
ON o.product_id = p.product_id )
SELECT
order_id,
product_id,
deliverytime
FROM CTE
WHERE rn = 1;
ORDER BY order_id
Maybe it should work for you, but if there are two or more products with the same highest value, you'd get more than 1 row per order:
select v.order_id
, p2.product_id
, p2.deliverytime
from (
select o.order_id
, max(p.deliverytime) as max_deliverytime
from Orderlines o
join Products p
on o.product_id = p.product_id
group by o.order_id
) v
join Products p2
on v.max_deliverytime = p2.deliverytime;
it is better to use row_number to get highest delivery_time row. we can also order it based on highest product_id if there is more than 1 highest delivery time
SELECT ol.order_id,
ol.product_id,
p.deliverytime
FROM (
SELECT ol.order_id,
ol.product_id,
p.deliverytime,
row_number() over(partition by ol.order_id
order by p.deliverytime desc, ol.product_id desc) rn
FROM orderline ol
JOIN products p
ON ol.product_id = p.product_id
)RPR
WHERE rn = 1

Retrieve the minimal create date with multiple rows

I have an issue with an SQL query that I am trying to write. I am trying to retrieve the row that has the minimal create_dt for each inst (see table) and amount (which isn't unique).
Unfortunately I can't use group by as the amount column isn't unique.
+--------------+--------+------+-------------+
| Company_Name | Amount | inst | Create Date |
+--------------+--------+------+-------------+
| Company A | 1000 | 4545 | 01/10/2018 |
| Company A | 400 | 4545 | 01/11/2018 |
| Company A | 200 | 4545 | 31/10/2018 |
| Company B | 2000 | 4893 | 01/10/2016 |
| Company B | 212 | 4893 | 04/10/2016 |
| Company B | 100 | 4893 | 10/10/2017 |
| Company B | 20 | 4893 | 04/10/2018 |
+--------------+--------+------+-------------+
In the above example I expect to see:
+--------------+--------+------+-------------+
| Company_Name | Amount | inst | Create Date |
+--------------+--------+------+-------------+
| Company A | 1000 | 4545 | 01/10/2018 |
| Company B | 2000 | 4893 | 01/10/2016 |
+--------------+--------+------+-------------+
Code:
SELECT
bill_company, bill_name, account_no
FROM
dbo.customer_information;
SELECT
balance_id, balance_id2, minus_balance,new_balance,
create_date, account_no
FROM
dbo.btr
SELECT
balance_id, balance_id2, expired_Date, amount, balance_type, account_no
FROM
dbo.btr_balance
SELECT
balance_ist, expired_date, account_no, balance_type
FROM
dbo.BALANCE_inst
Retrieve the minimal create data for a balance instance with the lowest balance for a balance inst.
(SELECT
bill_company,
bill_name,
account_no,
balance_ist,
amount,
MIN(create_date)
FROM
dbo.mtr btr
LEFT JOIN
btr_balance btrb ON btr.balance_id = btrb.balance_id
AND btr.balance_id2 = btrb.balance_id2
LEFT JOIN
balance_inst bali ON btr.account_no = bali.account_no
AND btrb.expired_date = bali.expired_date
GROUP BY
bill_company, bill_name, account_no,amount, balance_ist)
I have seen some solutions about using correlated query but can't see to get my head around it.
Common Table Expression (CTE) will help you.
;with cte as (
select *, row_number() over(partition by company_name order by create_date) rn
from dbo.myTable
)
select * from cte
where rn = 1;
use row_number() i assumed bill_company is your company name
select * from
( SELECT bill_company,
bill_name,
account_no,
balance_ist,
amount,
create_date,
row_number() over(partition by bill_company order by create_date) rn
FROM dbo.mtr btr left join btr_balance btrb
on btr.balance_id = btrb.balance_id and btr.balance_id2 = btrb.balance_id2
left join balance_inst bali
on btr.account_no = bali.account_no and btrb.expired_date = bali.expired_date
) t where t.rn=1

Joining results of two joins

I am looking for the best way to create a query that will do the following(Note: This is just an example, I know this example can be written better, my real goal is a much more complex example, but follows a similar structure)
items
item_id | name | cost
1 | Water | 1.00
2 | Chips | 1.50
trans_local
local_id | item_id | date
1 | 1 | '2018-03-12'
2 | 1 | '2018-03-13'
3 | 2 | '2018-03-13'
trans_international
international_id | item_id | currency | date
1 | 1 | 'GBP' | '2018-03-11'
2 | 2 | 'EUR' | '2018-03-12'
3 | 2 | 'GBP' | '2018-03-12'
I'm looking to create a select statement a table that lists all transactions in it.
local_id | international_id | item_id | item_name | item_cost | currency | date
1 | null | 1 | Water | 1.00 | null | '2018-03-12'
2 | null | 1 | Water | 1.00 | null | '2018-03-13'
3 | null | 2 | Chips | 1.50 | null | '2018-03-13'
null | 1 | 1 | Water | 1.00 | 'GBP' | '2018-03-11'
null | 2 | 2 | Chips | 1.50 | 'EUR' | '2018-03-12'
null | 3 | 2 | Chips | 1.50 | 'GBP' | '2018-03-12'
items should be joined to either trans_local or trans_international. I know I can do this with LEFT OUTER JOIN, but I am unsure how to get results of all transactions together. I believe it would be a FULL JOIN but getting everything together is confusing me a bit. Any help would be greatly appreciated.
I think the the only way to achieve your result is to use a UNION query, something like following:
(
SELECT
NULL as international_id,
trans_local.local_id,
items.name as item_name,
items.cost as item_cost,
NULL as currency,
trans_local.date as date
FROM items
LEFT JOIN trans_local ON items.item_id = trans_local.item_id
)
UNION
(
SELECT
trans_international.international_id as international_id,
NULL as local_id,
items.name as item_name,
items.cost as item_cost,
trans_international.currency as currency,
trans_international.date as date
FROM items
LEFT JOIN trans_international ON items.item_id = trans_international.item_id
)
select local_id , international_id, A.item_id, item_name, item_cost,
currency, B.DATE
from items A
left outer join
trans_local B
on (A.item_id = B.item_id)
left outer join
trans_international C
on (A.item_id = C.item_id)
as per your requirement your item_id column is having all the values. so find the column on table for which u want all the values and make it as left outer join.
I think you want a union all:
select i.*, t.*
from ((select local_id, NULL as internationalid, item_id, null as currency, date
from trans_local
) union all
(select NULL as local_id, internationalid, item_id, currency, date
from trans_international
)
) t join
item i
on t.item_id = i.item_id;

SUM values in last row

I have table with values
+--------+------------+-------------+
| XPK | Money | NumOfDevices|
+--------+------------+-------------+
| 1 | 1000 | 2 |
| 2 | 2000 | 3 |
| 3 | 3000 | 4 |
+--------+------------+-------------+
Need to sum all values and to enter the asterisk "*" in entire row to separate TOTAL Values from other values, so result need to look something like this
+--------+------------+-------------+
| XPK | Money | NumOfDevice |
+--------+------------+-------------+
| 1 | 1000 | 2 |
| 2 | 2000 | 3 |
| 3 | 3000 | 4 |
|***********************************|
| TOTAL | 6000 | 9 |
+--------+------------+-------------+
Any idea ?
The easiest way for this is to use a UNION selecting the totals from the table:
Select Convert(Varchar (10), XPK) XPK,
Money,
NumOfDevices
From YourTable
Union
Select 'TOTAL' As XPK,
Sum(Money),
Sum(NumOfDevices)
From YourTable
Order By Case When XPK = 'TOTAL' Then 1 Else 0 End, XPK
Another method of doing this would be to use a GROUP BY WITH ROLLUP
Select Case When Grouping(XPK) = 1
Then 'TOTAL'
Else Convert(Varchar (10), XPK)
End As XPK,
Sum(Money) Money,
Sum(NumOfDevices) NumOfDevices
From YourTable
Group By XPK With Rollup
Order By Grouping(XPK)
IN Table ERP System SAP
select B.ItemCode as'Item No.',B.Dscription as'Item Description',B.Quantity,B.Price as'Sale Amt',B.LineTotal as'Total'
from ODLN A
inner join DLN1 B On A.DocEntry=B.DocEntry
union all
select 'Total',convert(nvarchar(10),sum(case when b.Dscription is not null then 1 else 0 end)),sum(b.quantity),sum(b.price),sum(b.lineTotal)
from ODLN A
inner join DLN1 B On A.DocEntry=B.DocEntry

Getting the whole row from grouped result

Here's a sample database table :
| ID | ProductID | DateChanged | Price
| 1 | 12 | 2011-11-11 | 93
| 2 | 2 | 2011-11-12 | 12
| 3 | 3 | 2011-11-13 | 25
| 4 | 4 | 2011-11-14 | 17
| 5 | 12 | 2011-11-15 | 97
Basically, what I want to happen is get the latest price of grouped by ProductID.
The result should be like this :
| ID | ProductID | Price
| 2 | 2 | 12
| 3 | 3 | 25
| 4 | 4 | 17
| 5 | 12 | 97
If you notice, the first row is not there because there is a new price for ProductID 12 which is the row of ID 5.
Basically, it should be something like get ID,ProductID and Price grouped by productID where DateChanged is the latest.
SELECT ID, ProductId, Price
FROM
(
SELECT ID, ProductId, Price
, ROW_NUMBER() OVER (PARTITION BY ProductID ORDER BY DateChanged DESC) AS rowNumber
FROM yourTable
) AS t
WHERE t.rowNumber = 1
SELECT ID, ProductID,DateChanged, Price
FROM myTable
WHERE ID IN
(
SELECT MAX(ID)
FROM myTable
GROUP BY ProductID
)
select a.id, a.productid, a.price
from mytable a,
(select productid, max(datechanged) as maxdatechanged
from mytable
group by productid) as b
where a.productid = b.productid and a.datechanged = b.maxdatechanged
SELECT ID, ProductId, Price
from myTable A
where DateChanged >= all
(select DateChanged
from myTable B
where B.ID = A.ID);