is there an equivalent to cross apply in Sql server syntaxe or in bigquery syntaxe.
I need to write this query without the cross apply:
select *
from t1
cross apply (select top 1 col1,col2,col3
from t2
where col1 = t1.col1
and (col2 = '0' or col2 = t1.col2)
and (col3 = '0' or (col3 = left(t1.col3) and t1.col4 = 'fr'))
order by col2 desc, col3 desc)
t1 called 'Delivery' contains deliveries informations:
Delivery_ID,Delivery_ShipmentDate,Country_Code,address_ZipCode and the providerservice_id
t2 called 'ProviderService' contains informations about the providerservice:
Providerservice_id,DCountry_ID , DZone_Code as well as a numeric ProviderService_DeliveryTime.
So each Delivery_ID has a ProviderService_ID
And For the same Providerservice we could have several distinct ProviderService_DeliveryTime according to the other columns in this table(DCountry_ID , DZone_Code)
So the final query will be:
Select t1.Delivery_ShipmentDate,t2.ProviderService_DeliveryTime
from Delivery t1
cross apply (select top 1 ProviderService_DeliveryTime,DCountry_ID , DZone_Code
from ProviderService
where ProviderService_id = t1.ProviderService_id
And (DCountry_ID = '0' or DCountry_ID = t1.Country_Code)
And (DZone_Code = '0' or (DZone_Code = left(t1.address_ZipCode,2) and t1.Country_Code='FR'))
order by t2.DCountry_ID desc, t2.DZone_Code desc)sq
In fact I need first to write the same query in sql server syntaxe and then to write it in Bigquery because BigQuery don't recognize "cross apply" operator.
I tried to do it with row_number window function but it did not work:
with cte as (Select t1.Delivery_ShipmentDate,t2.ProviderService_DeliveryTime,row_number() over (partition by t2.providerservice_id order by t2.DCountry_ID desc, t2.DZone_Code desc) as num
from Delivery t1
inner join providerservice t2 on t1.providerservice_id = t2.providerservice_id
And (DCountry_ID = '0' or DCountry_ID = t1.Country_Code)
And (DZone_Code = '0' or (DZone_Code = left(t1.address_ZipCode,2) and t1.Country_Code='FR')))
select * from cte where num = 1
it works only when I filter by delivery_id:
with cte as (Select t1.Delivery_ShipmentDate,t2.ProviderService_DeliveryTime,row_number() over (partition by t2.providerservice_id order by t2.DCountry_ID desc, t2.DZone_Code desc) as num
from Delivery t1
inner join providerservice t2 on t1.providerservice_id = t2.providerservice_id
And (DCountry_ID = '0' or DCountry_ID = t1.Country_Code)
And (DZone_Code = '0' or (DZone_Code = left(t1.address_ZipCode,2) and t1.Country_Code='FR'))
where delivery_id = xxxx)
select * from cte where num = 1
Can any one help me please? Thanks!!
Below is for BigQuery Standard SQL
#standardSQL
SELECT * EXCEPT(pos)
FROM (
SELECT *
ROW_NUMBER() OVER(PARTITION BY TO_JSON_STRING(t1) ORDER BY t2.col2 DESC, t2.col3 DESC) pos
FROM t1 INNER JOIN t2
ON t2.col1 = t1.col1
AND (t2.col2 = '0' OR t2.col2 = t1.col2)
AND (t2.col3 = '0' OR (t2.col3 = left(t1.col3) AND t1.col4 = 'fr'))
)
WHERE pos = 1
I wish you gave us some data to play with - but having absence of it - above is just quick shot for you to try
I checked this approach (of implementing CROSS APPLY in BigQuery) against classic example with customers and orders tables and it worked
Would correlated subquery work the same as cross apply?
select *
from t1 , (select col1,col2,col3
from t2
where col1 = t1.col1
and (col2 = '0' or col2 = t1.col2)
and (col3 = '0' or (col3 = left(t1.col3) and t1.col4 = 'fr'))
order by col2 desc, col3 desc
limit 1)
Related
The original question and schema are shown at the following link:
SQL query to retrieve the latest status of a process
The solution provided by #mendosi was perfect. However, now that the deadline for submission is past, management wants more information. I've been able to give them the information they want using the following query (incorporating the aforementioned solution into the "EXISTS" clause):
SELECT
proposalPackage.proposalPackageID, refProposalType.name, proposalPackage.title,
[user].lastName, [user].firstName, [user].email, [user].phone,
proposalReviewAction.approvalTypeID
FROM
proposalReviewAction, proposalPackage
INNER JOIN
refProposalType ON proposalPackage.proposalTypeID = refProposalType.proposalTypeID
INNER JOIN
proposalManagerAssignment ON proposalPackage.proposalPackageID = proposalManagerAssignment.proposalPackageID
INNER JOIN
[user] ON proposalManagerAssignment.userID = [user].userID
WHERE
EXISTS (SELECT ls.*
FROM
(SELECT
r.proposalPackageID, r.approvalTypeID,
RowNr = ROW_NUMBER() OVER (PARTITION BY r.proposalPackageID ORDER BY r.reviewedDate DESC)
FROM
proposalReviewAction AS r
JOIN
proposalPackage AS pp ON pp.proposalPackageID = r.proposalPackageID
WHERE
pp.proposalCallID = 7) AS ls
WHERE
ls.RowNr = 1
AND (ls.approvalTypeID = 50))
GROUP BY
proposalPackage.proposalTypeID, [user].lastName, [user].firstName,
[user].email, [user].phone, proposalPackage.title,
refProposalType.name, proposalManagerAssignment.isPrimary,
proposalPackage.proposalCallID, approvalTypeID,
proposalPackage.proposalPackageID, proposalReviewAction.approvalTypeID
HAVING
(proposalManagerAssignment.isPrimary = 1)
AND (proposalPackage.proposalCallID = 7)
AND (approvalTypeID = 50)
ORDER BY
proposalPackage.proposalPackageID
My problem seems to be that the subquery in the Exists clause returns 95 rows (as it should) limiting the results to those with a status of 50.
As I understand the EXISTS clause, the results should be limited to those records that "exist" in the subquery that follows... right? So, in this case, if a record does not exist in the subquery, it will not exist in the final result...??
The problem is, I'm getting 112 records when there are only 95 records to choose from (or join on) in the results list of the subquery.
So, I try to limit is by adding some additional qualifiers and joins to the subquery:
SELECT
proposalPackage.proposalPackageID, refProposalType.name,
proposalPackage.title,
[user].lastName, [user].firstName, [user].email, [user].phone,
proposalReviewAction.approvalTypeID
FROM
proposalReviewAction, proposalPackage
INNER JOIN
refProposalType ON proposalPackage.proposalTypeID = refProposalType.proposalTypeID
INNER JOIN
proposalManagerAssignment ON proposalPackage.proposalPackageID = proposalManagerAssignment.proposalPackageID
INNER JOIN
[user] ON proposalManagerAssignment.userID = [user].userID
WHERE
EXISTS (SELECT ls.*
FROM
(SELECT
r.proposalPackageID,
r.approvalTypeID,
RowNr = ROW_NUMBER() OVER (PARTITION BY r.proposalPackageID ORDER BY r.reviewedDate DESC)
FROM
proposalReviewAction AS r
JOIN
proposalPackage AS pp ON pp.proposalPackageID = r.proposalPackageID
WHERE
pp.proposalCallID = 7) AS ls
WHERE
ls.RowNr = 1
AND (ls.approvalTypeID = 50)) AS distinctified
INNER JOIN
proposalPackage ON distinctified.proposalPackageID = proposalPackage.proposalPackageID
INNER JOIN
refProposalApprovalType ON distinctified.approvalTypeID = refProposalApprovalType.approvalTypeID
GROUP BY
proposalPackage.proposalTypeID, [user].lastName, [user].firstName,
[user].email, [user].phone, proposalPackage.title, refProposalType.name,
proposalManagerAssignment.isPrimary, proposalPackage.proposalCallID,
approvalTypeID, proposalPackage.proposalPackageID, proposalReviewAction.approvalTypeID
HAVING
(proposalManagerAssignment.isPrimary = 1)
AND (proposalPackage.proposalCallID = 7)
AND (distinctified.approvalTypeID = 50)
ORDER BY
proposalPackage.proposalPackageID
Now, when I add the "AS distinctified" statement with a couple of JOINS to the subquery, I get a "SYNTAX ERROR near AS" error. I also get an "Expecting ( or SELECT" at each of the "HAVING" qualifiers.
I don't think I'm making this too complicated but that remains a possibility. It seems to me it is a matter (at this point) of overlooking a character somewhere.
Thanks in advance for the assist... AGAIN!!
This isn't really an answer to your much more complex example, but it should explain what the root cause is hopefully?
DECLARE #x TABLE (id INT);
INSERT INTO #x SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3;
DECLARE #y TABLE (id INT);
INSERT INTO #y SELECT 1 UNION ALL SELECT 3;
--This is what you are doing
SELECT * FROM #x WHERE EXISTS (SELECT * FROM #y);
--This is what you should be doing
SELECT * FROM #x x WHERE EXISTS (SELECT * FROM #y y WHERE y.id = x.id);
I really have no idea what you are trying to accomplish but here is what your query might look like with some aliases and formatting. I also moved the joins before the where clause and removed the alias on your EXISTS predicate. But you are referencing distinctified in the code which I just don't get. As such there are some issues in this query still but without an understanding of what the need is I don't know what to do to help.
SELECT pp.proposalPackageID
, pt.name
, pp.title
, u.lastName
, u.firstName
, u.email
, u.phone
, pra.approvalTypeID
FROM proposalReviewAction pra
--, proposalPackage pp --why is this table here? It is joined to again later
INNER JOIN refProposalType pt ON pp.proposalTypeID = pt.proposalTypeID
INNER JOIN proposalManagerAssignment ma ON pp.proposalPackageID = ma.proposalPackageID
INNER JOIN [user] u ON ma.userID = u.userID
INNER JOIN proposalPackage pp ON distinctified.proposalPackageID = pp.proposalPackageID
INNER JOIN refProposalApprovalType pat ON distinctified.approvalTypeID = pat.approvalTypeID
WHERE EXISTS
(
SELECT ls.*
FROM
(
SELECT r.proposalPackageID,
r.approvalTypeID,
RowNr = ROW_NUMBER() OVER (PARTITION BY r.proposalPackageID ORDER BY r.reviewedDate DESC)
FROM proposalReviewAction AS r
JOIN proposalPackage AS pp2 ON pp2.proposalPackageID = r.proposalPackageID
WHERE pp2.proposalCallID = 7
) AS ls
WHERE ls.RowNr = 1
AND ls.approvalTypeID = 50
)
GROUP BY pp.proposalTypeID
, u.lastName
, u.firstName
, u.email
, u.phone
, pp.title
, pt.name
, ma.isPrimary
, pp.proposalCallID
, approvalTypeID
, pp.proposalPackageID
, pra.approvalTypeID
HAVING ma.isPrimary = 1
AND pp.proposalCallID = 7
AND distinctified.approvalTypeID = 50
ORDER BY pp.proposalPackageID
So, I figured it out... once I realized I had the wrong understanding of EXISTS (thanks #Richard Hansel). Final query: (properly formatted and aliased)
SELECT pp.proposalPackageID
, r_pt.name
, pp.title
, u.lastName
, u.firstName
, u.email
, u.phone
, pra.approvalTypeID
FROM proposalReviewAction AS pra
, proposalPackage AS pp
INNER JOIN refProposalType AS r_pt ON pp.proposalTypeID = r_pt.proposalTypeID
INNER JOIN proposalManagerAssignment AS pma ON pp.proposalPackageID = pma.proposalPackageID
INNER JOIN [user] AS u ON pma.userID = u.userID
WHERE EXISTS
(SELECT ls.*
FROM
(SELECT r.proposalPackageID,
r.approvalTypeID,
RowNr = ROW_NUMBER() OVER (PARTITION BY r.proposalPackageID ORDER BY r.reviewedDate DESC)
FROM proposalReviewAction AS r
JOIN proposalPackage AS pp ON pp.proposalPackageID = r.proposalPackageID
WHERE pp.proposalCallID = 7) AS ls
WHERE ls.RowNr = 1
AND (ls.approvalTypeID = 50)
AND (pra.proposalPackageID = pp.proposalPackageID))
GROUP BY pp.proposalTypeID
, u.lastName
, u.firstName
, u.email
, u.phone
, pp.title
, r_pt.name
, pma.isPrimary
, pp.proposalCallID
, approvalTypeID
, pp.proposalPackageID
, pra.approvalTypeID
HAVING (pma.isPrimary = 1)
AND (pp.proposalCallID = 7)
AND (pra.approvalTypeID = 50)
ORDER BY pp.proposalTypeID
WITH TEMP_CTE (ID,currentposition,equiptmentno,isocode,carrier,ishazardous,isreefer,CallID)
AS
(
SELECT a.ID,
a.newposition AS currentposition,
qce.equiptmentno,
qce.isocode,
qce.carrier,
qcee.ishazardous,
qcee.isreefer,qce.CallID
FROM (SELECT Row_number()
OVER (
partition BY callequipmentid
ORDER BY e.movedate DESC) RN,
e.*
FROM qbtcallequipmentexecution e
WHERE e.isactive = 1)a
INNER JOIN qbtcallequipment AS qce
ON a.callequipmentid = qce.id
AND qce.callid = #CallID
AND a.rn = 1
AND operationtype = 'LOAD'
INNER JOIN qbtcallediequipment AS qcee
ON qcee.equiptmentno = qce.equiptmentno
INNER JOIN qbtcalledi qcd
ON qcee.callediid = qcd.id
AND qcd.callid = #CallID
INNER JOIN commlov cl
ON cl.id = qcd.editypeid
AND cl.code = 'MOVINS'
AND siteid = #SiteID
UNION ALL
SELECT ddqce.ID,
ddqce.currentposition AS currentposition,
dqcee.equiptmentno,
dqcee.isocode,
dqcee.carrier,
dqcee.ishazardous,
dqcee.isreefer,ddqce.CallID
FROM qbtcallediequipment AS dqcee
INNER JOIN qbtcalledi dqcd
ON dqcee.callediid = dqcd.id
AND dqcd.callid = #CallID
INNER JOIN commlov dcl
ON dcl.id = dqcd.editypeid
AND dcl.code = 'RDBAPL'
AND siteid = #SiteID
INNER JOIN qbtcallequipment ddqce
ON ddqce.equiptmentno = dqcee.equiptmentno
AND ddqce.callid = #CallID
AND ddqce.isactive = 1
WHERE dqcee.equiptmentno NOT IN (SELECT dqce.equiptmentno
FROM (SELECT Row_number()
OVER (
partition BY
callequipmentid
ORDER BY e.movedate DESC)
RN,
e.*
FROM qbtcallequipmentexecution e
WHERE e.isactive = 1)a
INNER JOIN qbtcallequipment dqce
ON a.callequipmentid = dqce.id
AND dqce.callid = #CallID
AND a.rn = 1
AND movetypeid = (SELECT id
FROM
commlov
WHERE
code =
'DSCR'
AND
siteid =
#SiteID))
),
FIRST_CTE
AS
(
select ID,currentposition,equiptmentno,isocode,carrier,ishazardous,isreefer,CallID, ROW_NUMBER() over (PARTITION by currentposition order by equiptmentno desc ) as RN from TEMP_CTE
),
SECOND_CTE
AS
(
select TC.ID,currentposition,equiptmentno,isocode,carrier,ishazardous,isreefer,CallID,'Flying' as Anomaly
from TEMP_CTE as TC
inner join schmtVesselSchedule svs on svs.ID=TC.CallID
inner join qbtVesselProfile AS QVP ON svs.VesselID=QVP.VesselID
WHERE (cast(RIGHT(TC.currentposition,2) as int)>2 AND cast(RIGHT(TC.currentposition,2) as int)<cast(QVP.MaxTierUnderDeck as int)) OR (cast (RIGHT(TC.currentposition,2) as int)>cast (QVP.StartNoOverDeck as int) AND cast (RIGHT(TC.currentposition,2) as int) < cast (QVP.EndNoOverDeck as int)) AND (LEFT(TC.currentposition, LEN(cast(TC.currentposition as int)-2)+(case when LEN(cast(RIGHT(TC.currentposition,2) as int)-2)=1 then '0'+CONVERT(varchar(10), (RIGHT(TC.currentposition,2)-2)) else CONVERT(varchar(10), (RIGHT(TC.currentposition,2)-2)) end )) is null)
)
select
ID,
currentposition,
equiptmentno,
isocode,
carrier,
ishazardous,
isreefer,CallID,(case when RIGHT(currentposition,2)='99' then 'Dummy' else 'Same Slot' end) as Anomaly
from FIRST_CTE where RN > 1 OR RIGHT(currentposition,2) = '99'
union all
select
ID,
currentposition,
equiptmentno,
isocode,
carrier,
ishazardous,
isreefer,CallID,Anomaly
from SECOND_CTE
Error comes in where condition of SECOND_CTE. In that i used temp_cte for data purpose and manupulate it over there. Giving Error "
Conversion failed when converting the nvarchar value 'RT' to data type
int
. I have changed data type nvarchar to varchar of that column it also not working.And there is not char value in that column. It works fine in ssms but not working from Visual Studio"
With this query what I need SQL to do is update a column value based on another column so that it grabs the most recent MAX ID.
select
max(T1id), t1.v_code
from
[Table1] T1
join
[Table2] t2 on t1.T1Code = t2.T2Code
where
t2.active = 0
and t1.t1activesw = 0
and t1.mapping not like '%selected%'
group by
t1.v_code
I'd like to join the select to the table on the version code id = max(t1.v_code) and then use the code as a sub select just not sure how to finish it.
With this, you get all data from the row for with the highest T1.id for each T1.v_code:
;WITH CTE as
(
SELECT
T1.*,
row_number() over (partition by T1.v_code order by T1.id desc) rn
FROM
[Table1] T1
JOIN
[Table2] t2 on t1.T1Code = t2.T2Code
WHERE
t2.active = 0
and t1.t1activesw = 0
and t1.mapping not like '%selected%'
)
SELECT *
FROM CTE
WHERE rn = 1
Edit: In order to update, replace(as requested in commment)
SELECT *
FROM CTE
WHERE rn = 1
with
UPDATE CTE
SET columnname = 'newvalue'
WHERE rn = 1
this
I have a Select with sub selects using Top 1 and where clause.
I tried to optimize the select by doing a Left Join of the sub selects but the query time took longer. Is subselect better in this case? I couldnt post my whole select because it is too long and confidential but I will try to recreate the important part below:
Sub Select
SELECT
(select top 1 colId FROM table1 WHERE col1 = b.Id and col2 = 3 Order by 1) Id3,
(select top 1 colId FROM table1 WHERE col1 = b.Id and col2 = 5 Order by 1) Id5,
(select top 1 colId FROM table1 WHERE col1 = b.Id and col2 = 7 Order by 1) Id7
FROM table2 b
Trying it w/ Left Join
SELECT
t1.colid id3,
t2.colid id5,
t3.colid id7
FROM table2 b
LEFT JOIN (
select colId, col1 FROM table1 WHERE col2 = 3
) t1 ON t1.col1 = b.Id
LEFT JOIN (
select colId, col1 FROM table1 WHERE col2 = 5
) t2 ON t1.col1 = b.Id
LEFT JOIN (
select colId, col1 FROM table1 WHERE col2 = 7
) t3 ON t1.col1 = b.Id
Is there a better way to do this? and why is it the Left join takes longer query time?
You can use ROW_NUMBER:
;WITH cte AS
(
SELECT a.colId,
rn = ROWN_NUMBER() OVER (PARTITION BY a.col2 ORDER BY a.col1)
FROM table1 a
LEFT JOIN table2 b on a.col1 = b.id
WHERE a.col2 IN (3,5,7)
)
SELECT *
FROM cte
WHERE rn = 1
This will give you the first row for each col2 value and you can restrict the values you want to 3,5,7.
I have a ProductStatus table as listed below. I need to list all products whose latest status is “SU”. Along with that I need to list what was the previous status of this product.
Based on referring various posts, it seems like CROSS APPLY will be suitable for this. I made an attempt as listed below but that didn’t give the expected result.
What is the best way to achieve this in SQL Server 2005 (without using subquery)?
DECLARE #ProductStatus TABLE (ProductStatusID INT, productCode VARCHAR(5), statusCode VARCHAR(2))
INSERT INTO #ProductStatus
SELECT 1,'10011','RE' --Recevied
UNION
SELECT 2,'10011','SU' --Suspended
UNION
SELECT 3,'10012','IT' -- In Transit
UNION
SELECT 4,'10012','RE' -- Received
UNION
SELECT 10,'10012','PR' -- Produced
UNION
SELECT 12,'10012','SU' -- Suspended
UNION
SELECT 14,'10013','RE' -- Recevied
UNION
SELECT 16,'10014','SU' -- Recevied
UNION
SELECT 18,'10014','RE' -- Recevied
CROSS APPLY attempt
SELECT *
FROM #ProductStatus P
CROSS APPLY
(
SELECT MAX(V.ProductStatusID) as maxVal
FROM #ProductStatus V
WHERE V.ProductCode = P.ProductCode
AND V. ProductStatusID < P.ProductStatusID
GROUP BY V.ProductCode
)ML
WHERE P.statusCode = 'SU'
EXPECTED RESULT
You can do this with cross apply but I think row_number() is an easier approach:
select ProductCode,
max(case when seqnum = 1 then statusCode end) as LastStatus,
max(case when seqnum = 2 then statusCode end) as PrevStatus
from (select p.*,
row_number() over (partition by ProductCode order by ProductStatusId desc) as seqnum
from #ProductStatus p
) p
group by ProductCode
having max(case when seqnum = 1 then statusCode end) = 'SU';
Lijo, I've structured it as a CTE so you can see how I've developed my ideas. You can refactor it as sub-queries without affecting the meaning if you are more comfortable with those.
;with MostRecentStatus as (
select
MAX(ProductStatusID) as ProductStatusID,
productCode
from #ProductStatus as p1
group by productCode
)
,MostRecentIsSU as (
select
p2.ProductStatusID,
p2.productCode,
p2.statusCode
from MostRecentStatus as mrs
inner join #ProductStatus as p2
on p2.ProductStatusID = mrs.ProductStatusID
and p2.statusCode = 'SU'
)
select
m.ProductStatusID,
m.productCode,
m.statusCode,
p3.statusCode as PrevStatus,
p3.ProductStatusID as PrevProductStatusID
from MostRecentIsSU as m
left outer join #ProductStatus as p3
on p3.productCode = m.productcode
and p3.ProductStatusID = m.ProductStatusID - 1;
Edit: ..and here's the ROW_NUMBER() version with kudos to #attila.
;with InSquence as
(
select
ProductStatusID,
productCode,
statusCode,
ROW_NUMBER() OVER(PARTITION BY productCode ORDER BY ProductStatusID desc) as Sequence
from #ProductStatus
)
,FirstIsSU as
(
select
ProductStatusID,
productCode
from InSquence
where Sequence = 1
and statusCode = 'SU'
)
,PreviousCode as
(
select
ProductStatusID,
productCode,
statusCode
from InSquence
where Sequence = 2
)
select
f.ProductStatusID,
f.productCode,
'SU' as CurrentStatus,
p.statusCode as PrevStatus,
p.ProductStatusID as PrevProductStatusID
from FirstIsSU as f
left outer join PreviousCode as p
on p.productCode = f.ProductCode;
Here is a convoluted solution which serves mainly to illustrate that this should probably be done using row_number() :)
SELECT
F.productCode, F.statusCode, F.productStatusID, F.PriorProductStatusID, PriorStatus.statusCode
FROM
(
SELECT
PCS.productCode, PCS.statusCode, PCS.productStatusID, MAX(PS.productStatusID) PriorProductStatusID
FROM
(
SELECT productCode, MAX(productStatusID) productStatusID
FROM #ProductStatus
GROUP BY productCode
) LatestStatus
INNER JOIN
#ProductStatus PCS
ON PCS.productCode = LatestStatus.productCode
AND PCS.productStatusID = LatestStatus.productStatusID
AND PCS.statusCode = 'SU'
LEFT OUTER JOIN
#ProductStatus PS
ON PS.productCode = PCS.productCode
AND PS.productStatusID < PCS.productStatusID
GROUP BY PCS.productCode, PCS.statusCode, PCS.productStatusID
) F
LEFT OUTER JOIN
#ProductStatus PriorStatus
ON F.productCode = PriorStatus.productCode
AND F.PriorProductStatusID = PriorStatus.ProductStatusID