SQL show records that don't exist in my table variable - sql

I have a table variable that holds orderID, UnitID and OrderServiceId (it is already populated via a query with insert statement).
I then have a query under this that returns 15 columns which also include the OrderId, UnitId, OrderServiceId
I need to only return the rows from this query where the same combination of OrderId, UnitId, and OrderServiceId are not in the table variable.

You can use NOT EXISTS. e.g.
FROM YourQuery q
WHERE NOT EXISTS
(
SELECT * FROM #TableVar t
WHERE t.OrderId = q.OrderId
and t.UnitId = q.UnitId
and t.OrderServiceId=q.OrderServiceId
)

select q.*
from (
MyQuery
) q
left outer join MyTableVariable t on q.ORDERID = t.ORDERID
and q.UNITID= t.UNITID
and q.ORDERSERVICESID = t.ORDERSERVICESID
where t.ORDERID is null

You can use EXCEPT | INTERSECT operators for this (link).
Example:
(select 3,4,1
union all
select 2,4,1)
intersect
(select 1,2,9
union all
select 3,4,1)

Related

Unable to convert this legacy SQL into Standard SQL in Google BigQuery

I am not able to validate this legacy sql into standard bigquery sql as I don't know what else is required to change here(This query fails during validation if I choose standard SQL as big query dialect):
SELECT
lineitem.*,
proposal_lineitem.*,
porder.*,
company.*,
product.*,
proposal.*,
trafficker.name,
salesperson.name,
rate_card.*
FROM (
SELECT
*
FROM
dfp_data.dfp_order_lineitem
WHERE
DATE(end_datetime) >= DATE(DATE_ADD(CURRENT_TIMESTAMP(), -1, 'YEAR'))
OR end_datetime IS NULL ) lineitem
JOIN (
SELECT
*
FROM
dfp_data.dfp_order) porder
ON
lineitem.order_id = porder.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_proposal_lineitem) proposal_lineitem
ON
lineitem.id = proposal_lineitem.dfp_lineitem_id
JOIN (
SELECT
*
FROM
dfp_data.dfp_company) company
ON
porder.advertiser_id = company.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_product) product
ON
proposal_lineitem.product_id=product.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_proposal) proposal
ON
proposal_lineitem.proposal_id=proposal.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_rate_card) rate_card
ON
proposal_lineitem.ratecard_id=rate_card.id
LEFT JOIN (
SELECT
id,
name
FROM
dfp_data.dfp_user) trafficker
ON
porder.trafficker_id =trafficker.id
LEFT JOIN (
SELECT
id,
name
FROM
dfp_data.dfp_user) salesperson
ON
porder. salesperson_id =salesperson.id
Most likely the error you are getting is something like below
Duplicate column names in the result are not supported. Found duplicate(s): name
Legacy SQL adjust trafficker.name and salesperson.name in your SELECT statement into respectively trafficker_name and salesperson_name thus effectively eliminating column names duplication
Standard SQL behaves differently and treat both those columns as named name thus producing duplication case. To avoid it - you just need to provide aliases as in example below
SELECT
lineitem.*,
proposal_lineitem.*,
porder.*,
company.*,
product.*,
proposal.*,
trafficker.name AS trafficker_name,
salesperson.name AS salesperson_name,
rate_card.*
FROM ( ...
You can easily check above explained using below simplified/dummy queries
#legacySQL
SELECT
porder.*,
trafficker.name,
salesperson.name
FROM (
SELECT 1 order_id, 'abc' order_name, 1 trafficker_id, 2 salesperson_id
) porder
LEFT JOIN (SELECT 1 id, 'trafficker' name) trafficker
ON porder.trafficker_id =trafficker.id
LEFT JOIN (SELECT 2 id, 'salesperson' name ) salesperson
ON porder. salesperson_id =salesperson.id
and
#standardSQL
SELECT
porder.*,
trafficker.name AS trafficker_name,
salesperson.name AS salesperson_name
FROM (
SELECT 1 order_id, 'abc' order_name, 1 trafficker_id, 2 salesperson_id
) porder
LEFT JOIN (SELECT 1 id, 'trafficker' name) trafficker
ON porder.trafficker_id =trafficker.id
LEFT JOIN (SELECT 2 id, 'salesperson' name ) salesperson
ON porder. salesperson_id =salesperson.id
Note: if you have more duplicate names - you need to alias all of them too

Replace no result

I have a query like this:
SELECT TV.Descrizione as TipoVers,
sum(ImportoVersamento) as ImpTot,
count(*) as N,
month(DataAllibramento) as Mese
FROM PROC_Versamento V
left outer join dbo.PROC_TipoVersamento TV
on V.IDTipoVersamento = TV.IDTipoVersamento
inner join dbo.PROC_PraticaRiscossione PR
on V.IDPraticaRiscossioneAssociata = PR.IDPratica
inner join dbo.DA_Avviso A
on PR.IDDatiAvviso = A.IDAvviso
where DataAllibramento between '2012-09-08' and '2012-09-17' and A.IDFornitura = 4
group by V.IDTipoVersamento,month(DataAllibramento),TV.Descrizione
order by V.IDTipoVersamento,month(DataAllibramento)
This query must always return something. If no result is produced a
0 0 0 0
row must be returned. How can I do this. Use a isnull for every selected field isn't usefull.
Use a derived table with one row and do a outer apply to your other table / query.
Here is a sample with a table variable #T in place of your real table.
declare #T table
(
ID int,
Grp int
)
select isnull(Q.MaxID, 0) as MaxID,
isnull(Q.C, 0) as C
from (select 1) as T(X)
outer apply (
-- Your query goes here
select max(ID) as MaxID,
count(*) as C
from #T
group by Grp
) as Q
order by Q.C -- order by goes to the outer query
That will make sure you have always at least one row in the output.
Something like this using your query.
select isnull(Q.TipoVers, '0') as TipoVers,
isnull(Q.ImpTot, 0) as ImpTot,
isnull(Q.N, 0) as N,
isnull(Q.Mese, 0) as Mese
from (select 1) as T(X)
outer apply (
SELECT TV.Descrizione as TipoVers,
sum(ImportoVersamento) as ImpTot,
count(*) as N,
month(DataAllibramento) as Mese,
V.IDTipoVersamento
FROM PROC_Versamento V
left outer join dbo.PROC_TipoVersamento TV
on V.IDTipoVersamento = TV.IDTipoVersamento
inner join dbo.PROC_PraticaRiscossione PR
on V.IDPraticaRiscossioneAssociata = PR.IDPratica
inner join dbo.DA_Avviso A
on PR.IDDatiAvviso = A.IDAvviso
where DataAllibramento between '2012-09-08' and '2012-09-17' and A.IDFornitura = 4
group by V.IDTipoVersamento,month(DataAllibramento),TV.Descrizione
) as Q
order by Q.IDTipoVersamento, Q.Mese
Use COALESCE. It returns the first non-null value. E.g.
SELECT COALESCE(TV.Desc, 0)...
Will return 0 if TV.DESC is NULL.
You can try:
with dat as (select TV.[Desc] as TipyDesc, sum(Import) as ToImp, count(*) as N, month(Date) as Mounth
from /*DATA SOURCE HERE*/ as TV
group by [Desc], month(Date))
select [TipyDesc], ToImp, N, Mounth from dat
union all
select '0', 0, 0, 0 where (select count (*) from dat)=0
That should do what you want...
If it's ok to include the "0 0 0 0" row in a result set that has data, you can use a union:
SELECT TV.Desc as TipyDesc,
sum(Import) as TotImp,
count(*) as N,
month(Date) as Mounth
...
UNION
SELECT
0,0,0,0
Depending on the database, you may need a FROM for the second SELECT. In Oracle, this would be "FROM DUAL". For MySQL, no FROM is necessary

Query, subquery and using as variables from subquery

Is it not possible to use the "as [item] and then use the item variable in the query.
For example:
select c.category as [category],c.orderby as [CatOrder], m.masterno, m.master
,-- select OUT (select count(*) from rentalitem ri with (nolock),
rentalitemstatus ris with (nolock),
rentalstatus rs with (nolock)
where ri.rentalitemid = ris.rentalitemid
and ris.rentalstatusid = rs.rentalstatusid
and ri.masterid = m.masterid
and rs.statustype in ('OUT', 'INTRANSIT', 'ONTRUCK')) as [qtyout]
,-- select OWNED owned=
(select top 1 mwq.qty
from masterwhqty mwq
where mwq.masterid = m.masterid)
, -([owned]-[qtyout]) as [Variance]
from master m
inner join category c on c.categoryid=m.categoryid and c.categoryid=#category
inner join inventorydepartment d on c.inventorydepartment=#department
I cannot seem to use qtyout or owned when calculating variance. How can I do that?
You can also use a table variable and then reference that table variable like you are trying to do above....here's an example from MSDN
USE AdventureWorks2012;
GO
DECLARE #MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25,
ModifiedDate = GETDATE()
OUTPUT inserted.BusinessEntityID,
deleted.VacationHours,
inserted.VacationHours,
inserted.ModifiedDate
INTO #MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM #MyTableVar;
GO
--Display the result set of the table.
SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
need to move your calculated fields into a subquery, and then use them by their alias in the outer query.
select subquery.*, -([owned]-[qtyout]) as [Variance]
from
(
select c.category as [category],c.orderby as [CatOrder], m.masterno, m.master
,-- select OUT (select count(*) from rentalitem ri with (nolock),
rentalitemstatus ris with (nolock),
rentalstatus rs with (nolock)
where ri.rentalitemid = ris.rentalitemid
and ris.rentalstatusid = rs.rentalstatusid
and ri.masterid = m.masterid
and rs.statustype in ('OUT', 'INTRANSIT', 'ONTRUCK')) as [qtyout]
,-- select OWNED owned=
(select top 1 mwq.qty
from masterwhqty mwq
where mwq.masterid = m.masterid) as [owned]
from master m
inner join category c on c.categoryid=m.categoryid and c.categoryid=#category
inner join inventorydepartment d on c.inventorydepartment=#department
) as subquery
YOu need to use a subquery:
select t.*,
([owned]-[qtyout]) as [Variance]
from (<something like your query here
) t
You query, even without the comments, doesn't quite make sense (select OUT (select . . . for isntance). But, the answer to your question is to define the base variables in a subquery or CTE and then subsequently use them.
And, you are calling the difference "variance". Just so you know, you are redefining the statistical meaning of the term (http://en.wikipedia.org/wiki/Variance), which is based on the squares of the differences.

Sql Server Selecting Distinct records and OrderBy NEWID()

this is the stored procdure, I need to select Distinct Records and display them in a random order but I am facing an error that selecting Distinct can not be used with newid(), so how can I walk around this ?
USE [OtlobODR]
GO
/****** Object: StoredProcedure [OtlobFood].[ListOffersItems] Script Date: 11/18/2012 13:01:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [OtlobFood].[ListOffersItems]
#Fk_CampaignID int
as
select distinct
CampaignID, CampaignOffers.OldPrice
, dbo.ItemSizes.IS_Id,
, dbo.Items.[Item_Description_L2] as Item_Description
, dbo.Items.[Item_Image]
, dbo.Items.[Item_Details]
, dbo.ItemSizes.[IS_Price] as Price
-- if null then it is not a featured meal
, dbo.ProviderItems.[PI_Id] as ProviderItems_PI_ID
, dbo.ItemCategories.[ItemCat_Id]
, dbo.Providers.Provider_Name_L2 as Provider_Name
, dbo.Providers.Provider_Menu_Logo
, dbo.Providers.Provider_Id
FROM Items
INNER JOIN ProviderItems ON Items.Item_Id = ProviderItems.Item_Id
INNER JOIN dbo.ItemSizes ON dbo.Items.Item_Id = dbo.ItemSizes.Item_Id
INNER JOIN CampaignOffers ON CampaignOffers.ItemID = ItemSizes.IS_Id
INNER JOIN dbo.ItemCategories ON dbo.Items.ItemCat_Id = dbo.ItemCategories.ItemCat_Id
INNER JOIN dbo.Providers ON dbo.ProviderItems.Provider_Id = dbo.Providers.Provider_Id
INNER JOIN dbo.Branches ON dbo.Providers.Provider_Id = dbo.Branches.Provider_Id
where Fk_CampaignID=#Fk_CampaignID
group by NEWID(),
CampaignID, CampaignOffers.OldPrice ,
dbo.ItemSizes.IS_Id,
dbo.Items.[Item_Description_L2],
dbo.Items.[Item_Image],
dbo.Items.[Item_Details],
dbo.ItemSizes.IS_Id,
dbo.ItemSizes.[IS_Price] ,
-- if null then it is not a featured meal
dbo.ProviderItems.[PI_Id] ,
dbo.ItemCategories.[ItemCat_Id],
dbo.Providers.Provider_Name_L2,
dbo.Providers.Provider_Menu_Logo
,dbo.Branches.Branch_Id,
dbo.Providers.Provider_Id,CampaignID,CampaignOffers.OldPrice
order by NEWID()
You need to push the SELECT DISTINCT into an inner query (at which point you can also lose the GROUP BY) then do a NEWID() in the outer query. The general form is
select
newid(), X.*
from
(
select distinct <cols>
from <tables>
where <whatever>
) X
order by 1
in your case I think this is what you want:
select
newid(), X.*
from
(
select distinct
CampaignID, CampaignOffers.OldPrice ,
dbo.ItemSizes.IS_Id,
dbo.Items.[Item_Description_L2] as Item_Description ,
dbo.Items.[Item_Image],
dbo.Items.[Item_Details],
dbo.ItemSizes.[IS_Price] as Price,
-- if null then it is not a featured meal
dbo.ProviderItems.[PI_Id] as ProviderItems_PI_ID,
dbo.ItemCategories.[ItemCat_Id],
dbo.Providers.Provider_Name_L2 as Provider_Name,
dbo.Providers.Provider_Menu_Logo,
dbo.Providers.Provider_Id
FROM
Items
INNER JOIN ProviderItems ON Items.Item_Id = ProviderItems.Item_Id
INNER JOIN dbo.ItemSizes ON dbo.Items.Item_Id = dbo.ItemSizes.Item_Id
inner join CampaignOffers ON CampaignOffers.ItemID = ItemSizes.IS_Id
INNER JOIN dbo.ItemCategories ON dbo.Items.ItemCat_Id = dbo.ItemCategories.ItemCat_Id
INNER JOIN dbo.Providers ON dbo.ProviderItems.Provider_Id = dbo.Providers.Provider_Id
INNER JOIN dbo.Branches ON dbo.Providers.Provider_Id = dbo.Branches.Provider_Id
where
Fk_CampaignID = #Fk_CampaignID
) X
order by 1
Remove the NEWID()'s from your query and surround it with
SELECT * FROM (
<your query>
) as t
ORDER BY NEWID()
This query doesn't make much sense, there is no aggregation, so what is the purpose of the group by statement? and grouping by a NEWID() is not going to get you any grouping's anyway.
Combine the superfluous group by with the distinct clause and it feels more like you have a join condition incorrect that is causing a cartesian, and you are desperately trying to use distinct and group by's to eliminate that cartesian, it certainly makes little sense to have them both in the statement, and the newid in the group by should be removed.

MySQL/SQL - When are the results of a sub-query avaliable?

Suppose I have this query
SELECT * FROM (
SELECT * FROM table_a
WHERE id > 10 )
AS a_results LEFT JOIN
(SELECT * from table_b
WHERE id IN
(SElECT id FROM a_results)
ON (a_results.id = b_results.id)
I would get the error "a_results is not a table". Anywhere I could use the re-use the results of the subquery?
Edit: It has been noted that this query doesn't make sense...it doesn't, yes. This is just to illustrate the question which I am asking; the 'real' query actually looks something like this:
SELECT SQL_CALC_FOUND_ROWS * FROM
( SELECT wp_pod_tbl_hotel . *
FROM wp_pod_tbl_hotel, wp_pod_rel, wp_pod
WHERE wp_pod_rel.field_id =12
AND wp_pod_rel.tbl_row_id =1
AND wp_pod.tbl_row_id = wp_pod_tbl_hotel.id
AND wp_pod_rel.pod_id = wp_pod.id
) as
found_hotel LEFT JOIN (
SELECT COUNT(*) as review_count, avg( (
location_rating + staff_performance_rating + condition_rating + room_comfort_rating + food_rating + value_rating
) /6 ) AS average_score, hotelid
FROM (
SELECT r. * , wp_pod_rel.tbl_row_id AS hotelid
FROM wp_pod_tbl_review r, wp_pod_rel, wp_pod
WHERE wp_pod_rel.field_id =11
AND wp_pod_rel.pod_id = wp_pod.id
AND r.id = wp_pod.tbl_row_id
AND wp_pod_rel.tbl_row_id
IN (
SELECT wp_pod_tbl_hotel .id
FROM wp_pod_tbl_hotel, wp_pod_rel, wp_pod
WHERE wp_pod_rel.field_id =12
AND wp_pod_rel.tbl_row_id =1
AND wp_pod.tbl_row_id = wp_pod_tbl_hotel.id
AND wp_pod_rel.pod_id = wp_pod.id
)
) AS hotel_reviews
GROUP BY hotel_reviews.hotelid
ORDER BY average_score DESC
AS sorted_hotel ON (id = sorted_hotel.hotelid)
As you can see, the sub-query which makes up the found_query table is repeated elsewhere downward as another sub-query, so I was hoping to re-use the results
You can not use a sub-query like this.
I'm not sure I understand your query, but wouldn't that be sufficient?
SELECT * FROM table_a a
LEFT JOIN table_b b ON ( b.id = a.id )
WHERE a.id > 10
It would return all rows from table_a where id > 10 and LEFT JOIN rows from table_b where id matches.