SQL Query date from two tables - sql

I am trying to write a query...
select * from inventoryinfo, purchaseorderiteminfo
where inventoryinfo.qtyinstock < inventoryinfo.minqty
and inventoryinfo.AISTATUS = '1'
and inventoryinfo.category <> 'Noritsu Parts'
and inventoryinfo.itemcode = purchaseorderiteminfo.itemcode
and purchaseorderiteminfo.status = '0'
It returns 10 items
On another table this query shows what items are ordered and on their way
select * from purchaseorderiteminfo
where status = '0'
It returns 8 items
I want to join these two query's to list the 10 items, so I have:
select * from inventoryinfo, purchaseorderiteminfo
where inventoryinfo.qtyinstock < inventoryinfo.minqty
and inventoryinfo.AISTATUS = '1'
and inventoryinfo.category <> 'Noritsu Parts'
and inventoryinfo.itemcode = purchaseorderiteminfo.itemcode
and purchaseorderiteminfo.status = '0'
BUT, it only shows 8 items because the other 2 items do not have an open PO for an order for them. Is there a way to have a list with all 10 items, even 2 of them don't have data in the purchaseorderiteminfo table?

You want to use aleft joinbetween the tables. This gets all rows from the main table, and the matching from the left joined.
select * from inventoryinfo
left join purchaseorderiteminfo on inventoryinfo.itemcode = purchaseorderiteminfo.itemcode and purchaseorderiteminfo.status = '0'
where inventoryinfo.qtyinstock < inventoryinfo.minqty
and inventoryinfo.AISTATUS = '1'
and inventoryinfo.category <> 'Noritsu Parts'
You can also use aliases for the tables to shorten the query a bit:
select * from inventoryinfo i
left outer join purchaseorderiteminfo p on i.itemcode = p.itemcode and p.status = '0'
where i.qtyinstock < i.minqty
and i.AISTATUS = '1'
and i.category <> 'Noritsu Parts'
Also notice that I replaced your old-style implicit joins:
from table1, table2
where table1.key = table2.key
with the explicit syntax used in ANSI standard SQL-92 and later:
FROM table1
LEFT [OUTER] JOIN table2 ON table1.key = table2.key
-- the OUTER keyword is optional in many databases.
See Bad habits to kick : using old-style JOINs for some reasons why you want to do this.

Related

Merge A nested Query with another result in SQLite

I have two sets of queries:
SELECT
t.series_name,
ti.num_views_per_telecast
FROM
(
SELECT
ti.telecast_id,
ti.network_id,
count(*) as num_views_per_telecast
FROM
tunein AS ti
INNER JOIN affiliates AS a ON ti.network_id = a.network_id
WHERE
ti.dvr_time_shift = 'L+SD'
and a.network_name = 'ABC'
group by
ti.telecast_id,
ti.network_id
) ti
inner join telecast AS t On t.telecast_id = ti.telecast_id
ORDER BY
ti.num_views_per_telecast DESC
And
select
distinct *
from
telecast
where
episode_name = 'friday night dinner'
and series_name = 'A Million Little Things'
and date(program_start_local) = '2018-10-17'
I want to be able to combine the two so that I can get the num_views_per_telecast for the episodes in the bottom query. Not quite sure how I would inner join these though so I could keep the results from the first set of queries.
How the tables are connected are below:
How would I combine these???
At a guess:
SELECT
t.*,
ti.num_views_per_telecast
FROM
(
SELECT
ti.telecast_id,
ti.network_id,
count(*) as num_views_per_telecast
FROM
tunein AS ti
INNER JOIN
affiliates AS a
ON
ti.network_id = a.network_id
WHERE
ti.dvr_time_shift = 'L+SD' and
a.network_name = 'ABC'
group by
ti.telecast_id,
ti.network_id
)ti
inner join telecast AS t
On
t.telecast_id = ti.telecast_id
--from query2
where
t.episode_name = 'friday night dinner'
and t.series_name = 'A Million Little Things'
and t.date(program_start_local) = '2018-10-17'
ORDER BY ti.num_views_per_telecast DESC
For reasons given in the comment, the DISTINCT is redundant so you seem to want all rows from telecast that match some criteria. Given that your first query contains telecast but without any criteria and you only select one column from it, merging the two is a case of boosting the number of columns selected to (all from telecast) plus anything else, and adding the where clause from query 2 to restrict the rows in query 1

Pulling cost field from a sub-query

I wrote the following query to pull a unit cost from another table COSreport into my profitability query ProfitabilityReport and am having a problem with my sub-query.
select
i.tranid
, it.item_id
, it.displayname
, tl.Item_Count * -1 Unit_Qty
, case when tl.Item_Count=0 then 0
else ((tl.GROSS_AMOUNT * -1)/ Item_Count) * -1
end as PricePerUnit,
**(select sum(c.tranamt) from ns.COSreport c
inner join ns.ProfitabilityReport d
on c.InvoiceID = d.tranid
and c.item_id = d.item_id) as 'True Cost'**
, '0' 'Cost Per M'
from ns.tinvoice i
join ns.transaction_lines tl on i.transaction_id = tl.transaction_id
join ns.Customers cust on c.customer_id = i.ENTITY_ID
join ns.items it on it.item_id = tl.item_id
left join ns.ITEM_CLASSIFICATION it_class on it_class.list_id =
it.ITEM_CLASSIFICATION_ID
where list_item_name IS NOT NULL
and i.tranid = '1262INV'
I'm joining on both the invoice id and item id so that the proper cost is pulled across for the given invoice and item from COSReport.
However, the true cost is not coming up with the unit cost but instead is summing up the cost field for the entire table.
See below for example using invoice # 1262INV specified in the query above. The cost should be 1.04, .26, and 4 respectively vs 138m.
Any help getting this cleared up would be appreciated
I actually prefer using CTEs for readability. You can take your subquery, put it into a CTE, and then join it in your main query, but you'll want to add the tranid and item_id fields to the CTE so you can use them in your join.
EDIT: since you're using Azure SQL Server, you don't need the semicolon before the WITH.
WITH TrueCosts AS
(
SELECT
d.tranid
,d.item_id
,TrueCost = SUM(c.tranamt)
FROM ns.COSreport c
INNER JOIN ns.ProfitabilityReport d
ON c.InvoiceID = d.tranid
AND c.item_id = d.item_id
GROUP BY d.tranid
,d.item_id
)
SELECT
i.tranid
, it.item_id
, it.displayname
, tl.Item_Count * -1 Unit_Qty
, case when tl.Item_Count=0 then 0
else ((tl.GROSS_AMOUNT * -1)/ Item_Count) * -1
END as PricePerUnit
, tc.TrueCost AS 'True Cost'
, '0' AS 'Cost Per M'
FROM ns.tinvoice i
JOIN ns.transaction_lines tl on i.transaction_id = tl.transaction_id
JOIN ns.Customers c on c.customer_id = i.ENTITY_ID
JOIN ns.items it on it.item_id = tl.item_id
LEFT JOIN ns.ITEM_CLASSIFICATION it_class on it_class.list_id = it.ITEM_CLASSIFICATION_ID
LEFT JOIN TrueCosts tc ON tc.tranid = i.tranid AND tc.item_id = tl.item_id
WHERE list_item_name IS NOT NULL
AND i.tranid = '1262INV'
You have a couple of problems.
In your subquery you use the alias c for COSReport. You also use the alias c for customers in your outer query.
The bigger problem is that your subquery isn't correlated to your outer query at all. That's why it's summing up the entire table.
To correlate your subquery, you need to join (in the subquery) to one of the tables in the outer query. Not sure of your tables or data, but at a guess, I'd say you want to use ns.tinvoice i in a WHERE clause in your subquery.

SQL Query with counts only returning equivalent counts

I have a query that consists of 1 table and 2 sub queries. The table being a listing of all customers, 1 sub query is a listing all of the quotes given over a period of time for customers and the other sub query is a listing of all of the orders booked for a customer over the same period of time. What I am trying to do is return a result set that is a customer, the number of quotes given, and the number of orders booked over a given period of time. However what I am returning is only a listening of customers over the period of time that have an equivalent quote and order count. I feel like I am missing something obvious within the context of the query but I am unable to figure it out. Any help would be appreciated. Thank you.
Result Set should look like this
Customer-------Quotes-------Orders Placed
aaa----------------4----------------4
bbb----------------9----------------18
ccc----------------18----------------9
select
[Customer2].[Name] as [Customer2_Name],
(count( Quotes.UD03_Key3 )) as [Calculated_CustomerQuotes],
(count( Customer_Bookings.OrderHed_OrderNum )) as [Calculated_CustomerBookings]
from Erp.Customer as Customer2
left join (select
[UD03].[Key3] as [UD03_Key3],
[UD03].[Key4] as [UD03_Key4],
[UD03].[Key1] as [UD03_Key1],
[UD03].[Date02] as [UD03_Date02]
from Ice.UD03 as UD03
inner join Ice.UD02 as UD02 on
UD03.Company = UD02.Company
And
CAST(CAST(UD03.Number09 AS INT) AS VARCHAR(30)) = UD02.Key1
left outer join Erp.Customer as Customer on
UD03.Company = Customer.Company
And
UD03.Key1 = Customer.Name
left outer join Erp.SalesTer as SalesTer on
Customer.Company = SalesTer.Company
And
Customer.TerritoryID = SalesTer.TerritoryID
left outer join Erp.CustGrup as CustGrup on
Customer.Company = CustGrup.Company
And
Customer.GroupCode = CustGrup.GroupCode
where (UD03.Key3 <> '0')) as Quotes on
Customer2.Name = Quotes.UD03_Key1
left join (select
[Customer1].[Name] as [Customer1_Name],
[OrderHed].[OrderNum] as [OrderHed_OrderNum],
[OrderDtl].[OrderLine] as [OrderDtl_OrderLine],
[OrderHed].[OrderDate] as [OrderHed_OrderDate]
from Erp.OrderHed as OrderHed
inner join Erp.Customer as Customer1 on
OrderHed.Company = Customer1.Company
And
OrderHed.BTCustNum = Customer1.CustNum
inner join Erp.OrderDtl as OrderDtl on
OrderHed.Company = OrderDtl.Company
And
OrderHed.OrderNum = OrderDtl.OrderNum) as Customer_Bookings on
Customer2.Name = Customer_Bookings.Customer1_Name
where Quotes.UD03_Date02 >= '5/15/2018' and Quotes.UD03_Date02 <= '5/15/2018' and Customer_Bookings.OrderHed_OrderDate >='5/15/2018' and Customer_Bookings.OrderHed_OrderDate <= '5/15/2018'
group by [Customer2].[Name]
You have several problems going on here. The first problem is your code is so poorly formatted it is user hostile to look at. Then you have left joins being logically treated an inner joins because of the where clause. You also have date literal strings in language specific format. This should always be the ANSI format YYYYMMDD. But in your case your two predicates are contradicting each other. You have where UD03_Date02 is simultaneously greater than and less than the same date. Thankfully you have =. But if your column is a datetime you have prevented any rows from being returned again (the first being your where clause). You have this same incorrect date logic and join in the second subquery as well.
Here is what your query might look like with some formatting so you can see what is going on. Please note I fixed the logical join issue. You still have the date problems because I don't know what you are trying to accomplish there.
select
[Customer2].[Name] as [Customer2_Name],
count(Quotes.UD03_Key3) as [Calculated_CustomerQuotes],
count(Customer_Bookings.OrderHed_OrderNum) as [Calculated_CustomerBookings]
from Erp.Customer as Customer2
left join
(
select
[UD03].[Key3] as [UD03_Key3],
[UD03].[Key4] as [UD03_Key4],
[UD03].[Key1] as [UD03_Key1],
[UD03].[Date02] as [UD03_Date02]
from Ice.UD03 as UD03
inner join Ice.UD02 as UD02 on UD03.Company = UD02.Company
And CAST(CAST(UD03.Number09 AS INT) AS VARCHAR(30)) = UD02.Key1
left outer join Erp.Customer as Customer on UD03.Company = Customer.Company
And UD03.Key1 = Customer.Name
left outer join Erp.SalesTer as SalesTer on Customer.Company = SalesTer.Company
And Customer.TerritoryID = SalesTer.TerritoryID
left outer join Erp.CustGrup as CustGrup on Customer.Company = CustGrup.Company
And Customer.GroupCode = CustGrup.GroupCode
where UD03.Key3 <> '0'
) as Quotes on Customer2.Name = Quotes.UD03_Key1
and Quotes.UD03_Date02 >= '20180515'
and Quotes.UD03_Date02 <= '20180515'
left join
(
select
[Customer1].[Name] as [Customer1_Name],
[OrderHed].[OrderNum] as [OrderHed_OrderNum],
[OrderDtl].[OrderLine] as [OrderDtl_OrderLine],
[OrderHed].[OrderDate] as [OrderHed_OrderDate]
from Erp.OrderHed as OrderHed
inner join Erp.Customer as Customer1 on OrderHed.Company = Customer1.Company
And OrderHed.BTCustNum = Customer1.CustNum
inner join Erp.OrderDtl as OrderDtl on OrderHed.Company = OrderDtl.Company
And OrderHed.OrderNum = OrderDtl.OrderNum
) as Customer_Bookings on Customer2.Name = Customer_Bookings.Customer1_Name
and Customer_Bookings.OrderHed_OrderDate >= '20180515'
and Customer_Bookings.OrderHed_OrderDate <= '20180515'
group by [Customer2].[Name]
COUNT() will just give you the number of records. You'd expect this two result columns to be equal. Try structuring it like this:
SUM(CASE WHEN Quote.UD03_Key1 IS NOT NULL THEN 1 ELSE 0 END) AS QuoteCount,
SUM(CASE WHEN Customer_Bookings.Customer1_Name IS NOT NULL THEN 1 ELSE 0 END) AS custBookingCount

Simplifying where clause when a column is mutual for the tables at from clause

I would like to learn if there is any more efficient way to write the query below:
SELECT *
FROM requests srp
INNER JOIN surgeons rpsur
ON rpsur.id = srp.surgeon_id
LEFT OUTER JOIN #usersurgeons usersurgeons
ON usersurgeons.surgeon_id = srp.surgeon_id
LEFT OUTER JOIN surgeons LOsurgeons
ON usersurgeons.surgeon_id = LOsurgeons.id
LEFT OUTER JOIN provsurgeons LOprovsurgeons
ON LOprovsurgeons.id = LOsurgeons.provsurgeon_id
INNER JOIN #selectedsurgeons up
ON up.surgeon_id = rpsur.id
LEFT OUTER JOIN provsurgeons ps
ON ps.id = rpsur.provsurgeon_id
WHERE rpsur.isprimary = 0
AND usersurgeons.isprimary = 0
AND LOsurgeons.isprimary = 0
AND LOprovsurgeons.isprimary = 0
AND up.isprimary = 0
AND ps.isprimary = 0
I am not happy with the where clause here, is there any more professional way to write this, rather than adding the clauses to the join lines (such as on xx.id = yy.id and xx.isPrimary=0)??
From this query alone there are not many things that can be said. You should consider adding some more context (how do you get data into those temporary tables and the structure of %surgeons tables):
1) Select * makes almost impossible to use any index and also provides a lot of columns (Requests.*, surgeons.*, Provsurgeons.* etc.) in your final result. Return only the columns that you need.
2) If isPrimary = 0 filtering is performed often in your queries (not just this one), you can consider creating a view that fetches data filtered by isPrimary = 0. E.g. vwSurgeons, vwProvsurgeons. Then, you can just JOIN directly to the view instead of the table.
3) [already mentioned in the comments] Any condition that excludes NULL values for the OUTER JOINed table will transform the OUTER into INNER.
Instead of joining all tables and having a where clause at the end, use a derived tables only with filtered records. This way your query performance will be better.
SELECT *
FROM requests srp
INNER JOIN surgeons rpsur
ON rpsur.id = srp.surgeon_id
LEFT OUTER JOIN
(
SELECT *
FROM #usersurgeons
WHERE isprimary = 0
)usersurgeons
ON usersurgeons.surgeon_id = srp.surgeon_id
LEFT OUTER JOIN
(
SELECT *
FROM surgeons
WHERE isprimary = 0
)LOsurgeons
ON usersurgeons.surgeon_id = LOsurgeons.id
LEFT OUTER JOIN
(
SELECT *
FROM provsurgeons
WHERE isprimary = 0
)LOprovsurgeons
ON LOprovsurgeons.id = LOsurgeons.provsurgeon_id
INNER JOIN
(
SELECT *
FROM #selectedsurgeons
WHERE isprimary = 0
)up
ON up.surgeon_id = rpsur.id
LEFT OUTER JOIN
(
SELECT *
FROM provsurgeons
WHERE isprimary = 0
) ps
ON ps.id = rpsur.provsurgeon_id
WHERE rpsur.isprimary = 0

Performing left join along with where condition

I was using this query to get results,
SELECT *
FROM TRXN_REPORT CNT,
TBL_CUSTINFO CUSTADDINFO,
TBL_DEAL_EVT EVENT,
TBL_MISCADDR CIFMISC
WHERE CNT.INTERNAL_REF_NUM = EVENT.INTERNAL_REF_NUM
AND CNT.BRANCH = EVENT.BRANCH
AND CNT.QFXVERSION = EVENT.QFXVERSION
AND CNT.VALUEDATE = EVENT.VALUEDATE
AND CNT.LIQ_STATUS = 'L'
AND EVENT.EVENTCODE = 'LLIQ' -- Liquidation Event
AND CUSTADDINFO.CUSTOMER_NO = CNT.CUST_NUM
AND CIFMISC.CUSTOMER_NUMBER = CNT.CUST_NUM
AND CUSTADDINFO.REC_STATUS ='O'
AND CIFMISC.REC_STATUS = 'O'
AND MY_PBG_CUSTOMER = 'Y'
AND (BUYCCYCODE = 'USD' OR SELLCCYCODE ='USD')
here this condition
AND CIFMISC.CUSTOMER_NUMBER = CNT.CUST_NUM
Is fetching only those records which are present both in TBL_MISCADDR and TRXN_REPORT table, now as a change of requirment I want to perform left outer join so as to get records which are not there in TBL_MISCADDR table but present in TRXN_BATCHREPORT_WRK. How to perform this along with maintaining all the where conditions.
You have to you specify the condition for the join in the ON clause of the JOIN. So, your current conditions in the WHERE clause should be separated into the conditions for joining the tables (and these moved to ON clause), and the rest for selecting the lines - and these should be left in the WHERE clause. Example (don't know if I have it correct according to your data but you will get the idea):
SELECT *
FROM TRXN_REPORT CNT
LEFT JOIN TBL_DEAL_EVT EVENT ON
CNT.INTERNAL_REF_NUM = EVENT.INTERNAL_REF_NUM
AND CNT.BRANCH = EVENT.BRANCH
AND CNT.QFXVERSION = EVENT.QFXVERSION
AND CNT.VALUEDATE = EVENT.VALUEDATE
LEFT JOIN SOME_OTHER_TABLE T ON
...
WHERE
AND CUSTADDINFO.REC_STATUS ='O'
AND CIFMISC.REC_STATUS = 'O'
AND MY_PBG_CUSTOMER = 'Y'
AND (BUYCCYCODE = 'USD' OR SELLCCYCODE ='USD')
....
This way you can safely use LEFT JOIN and the lines for which the records doesn't exist in the other table will also be included.
... to get records which are not there in TBL_MISCADDR table but
present in TRXN_BATCHREPORT_WRK.
That would be done using TRXN_BATCHREPORT_WRK LEFT JOIN TBL_MISCADDR ON <condition>.