BigQuery - Delete based on values from another table - sql

I'm trying to delete rows from one table, based on the second table using INNER JOIN on BigQuery, but it keeps giving error.
The context is simple, I have an input table that I'm fetching the dates contained there, and on the historic table, I want to delete those dates in order to put them after the delete.
The code that I have now is the following, however it's returning the error
Syntax error: Expected end of input but got keyword INNER at [3:1]
DELETE
FROM `datapool-prt-supplychain-wrk.TRANSPORTS_DATA.tbl_historico_tb_rota` AS a
INNER JOIN
(SELECT DISTINCT
CAST(
CONCAT(RIGHT(data,4),'-',
CASE
WHEN LENGTH(data) = 8 THEN
CONCAT('0',SUBSTR(data ,3,1),'-0',LEFT(data ,1))
WHEN LENGTH(data) = 9 AND SUBSTR(data,3,1) = "-" THEN
CONCAT('0',SUBSTR(data ,4,1),"-",LEFT(data ,2))
WHEN LENGTH(data) = 9 THEN
CONCAT(SUBSTR(data ,3,2),'-0',LEFT(data ,1))
WHEN LENGTH(data) = 10 THEN
CONCAT(SUBSTR(data,4,2),'-',LEFT(data,2))
ELSE '1900-01-01'
END
)
AS DATE ) AS data
FROM `datapool-prt-supplychain-wrk.TRANSPORTS_DATA.tbl_input_tb_rota`) AS b ON b.data = a.data
WHERE b.data IS NOT NULL

Try to move your join logic to an exists clause
delete from `datapool-prt-supplychain-wrk.TRANSPORTS_DATA.tbl_historico_tb_rota` AS a
where exists (
select 1
from `datapool-prt-supplychain-wrk.TRANSPORTS_DATA.tbl_input_tb_rota` b
where
CAST(
CONCAT(
RIGHT(b.data,4),'-',
CASE
WHEN LENGTH(b.data) = 8 THEN
CONCAT('0',SUBSTR(b.data ,3,1),'-0',LEFT(b.data ,1))
WHEN LENGTH(b.data) = 9 AND SUBSTR(b.data,3,1) = "-" THEN
CONCAT('0',SUBSTR(b.data ,4,1),"-",LEFT(b.data ,2))
WHEN LENGTH(b.data) = 9 THEN
CONCAT(SUBSTR(b.data ,3,2),'-0',LEFT(b.data ,1))
WHEN LENGTH(b.data) = 10 THEN
CONCAT(SUBSTR(b.data,4,2),'-',LEFT(b.data,2))
ELSE '1900-01-01'
END
)
AS DATE ) = a.data
)

Related

Bizarre Join with comma

I'm looking at someone else's code and find this bizarre join:
SELECT
SUM(
(
intUnitOverheadCost + intUnitLaborCost + intUnitMaterialCost + intUnitSubcontractCost
+ intUnitDutyCost + intUnitFreightCost + intUnitMiscCost
)
*
(
(
CASE
WHEN imtSource = 3
THEN - 1
ELSE 1
END
) * intQuantity
)
)
FROM PartTransactions --imt
INNER JOIN PartTransactionCosts --int
ON imtPartTransactionID = intPartTransactionID
LEFT JOIN Warehouses --imw
ON imtPartWarehouseLocationID = imwWarehouseID
, ProductionProperties --xap <-- weird join
WHERE imtJobID = jmpJobID
AND imtSource IN (2,3)
AND imtReceiptID = ''
AND Upper(imtTableName) <> 'RECEIPTLINES'
AND imtNonInventoryTransaction <= {?CHECKBOXGROUP_4_ShowNonInventory}
AND imtJobType IN (1, 3)
AND imtTransactionDate < DATEADD(d, 1, {?PROMPT_1_TODATE})
AND (
imtNonNettable = 0
OR (
imtNonNettable <> 0
AND ISNULL(imwDoNotIncludeInJobCosts, 0) = 0
)
)
AND intCostType = (
CASE -- Always 1
WHEN xapIMCostingMethod = 1
THEN 1
WHEN xapIMCostingMethod = 2
THEN 2
WHEN xapIMCostingMethod = 3
THEN 3
ELSE 4
END
)
There is only one record in table ProductionProperties and the result of select xapIMCostingMethod from ProductionProperties is always 1.
There are always 4 enumerated results in PartTransactionCosts, but only 1 result is allowed.
ProductionProperties.xapIMCostingMethod is implicitly joining to PartTransactionCosts.intCostType
My specific question is what is really going on with this comma join? It looks like it has to be a cross-join, later filtered in the WHERE clause with one possible result.
Agree with the previous answer. It is a cartesian join but since the rows are 1 it doesn't cause an issue.
I'm thinking if you added rows to ProductionProperties then it would serve as a multiplier for your sum. I did a little experiment to show the issue:
declare #tableMoney table (
unit int,
Product char(5),
xapIMPCostingMethod int,
Cost money
)
declare #tableProdProperties table (
xapIMPCostingMethod int
)
insert #tableMoney (unit, Product, xapIMPCostingMethod, Cost)
values
(1,'bike',1, 2.00),
(1,'car',1, 2.25),
(2,'boat',2, 4.50)
insert #tableProdProperties (xapIMPCostingMethod)
values (1),
(2)
select sum(Cost)
from #tableMoney, #tableProdProperties
I also don't like to use joins where it isn't clear what is joining to what so I always use an alias:
select sum(Cost)
from #tableMoney tbm join #tableProdProperties tpp
on tbm.xapIMPCostingMethod = tpp.xapIMPCostingMethod

select subquery using data from the select statement?

I have two tables, headers and lines. I need to grab the batch_submission_date from the header table, but sometimes a query for batch_id will return a null for batch_submission_date, but will also return a parent_batch_id, and if we query THAT parent_batch_id as a batch_id, it will then return the correct batch_submission_date.
e.g.
SELECT t1.batch_id,
t1.parent_batch_id,
t2.batch_submission_date
FROM db.headers t1, db.lines t2
WHERE t1.batch_id = '12345';
output = 12345, 99999, null
Then we use that parent batch_id as a batch_id :
SELECT t1.batch_id,
t1.parent_batch_id,
t2.batch_submission_date
FROM db.headers t1, db.lines t2
WHERE t1.batch_id = '99999';
and we get output = 99999,99999,'2018-01-01'
So I'm trying to write a query that will do this for me - anytime a batch_id's batch_submission_date is null, we find that batch_id's parent batch_id and query that instead.
This was my idea - but I just get back null both for bp_batch_submission_date and for new_submission_date.
SELECT
t1.parent_id as parent_id,
t1.BATCH_ID as bp_batch_id,
t2.BATCH_LINE_NUMBER as bp_batch_li,
t1.BATCH_SUBMISSION_DATE as bp_batch_submission_date,
CASE
WHEN t1.BATCH_SUBMISSION_DATE is null
THEN
(SELECT a.BATCH_SUBMISSION_DATE
FROM
db.headers a,
db.lines b
WHERE
a.SD_BATCH_HEADERS_SKEY = b.SD_BATCH_HEADERS_SKEY
and a.parent_batch_id = bp_batch_id
and b.batch_line_number = bp_batch_li
) END as new_submission_date
FROM
db.headers t1,
db.lines t2
WHERE
t1.SD_BATCH_HEADERS_SKEY = t2.SD_BATCH_HEADERS_SKEY
and (t1.BATCH_ID = '12345' or t1.PARENT_BATCH_ID = '12345')
and t2.BATCH_LINE_NUMBER = '1'
GROUP BY
t2.BATCH_CLAIM_LINE_STATUS_DESC,
t1.PARENT_BATCH_ID,
t1.BATCH_ID,
t2.BATCH_LINE_NUMBER,
t1.BATCH_SUBMISSION_DATE;
is what I'm trying to do possible? using the bp_batch_id and bp_batch_li variables
Use CTE (common table expression) to avoid redundant code, then use coalesce() to find parent date in case of null. In your first queries you didn't attach joining condition between two tables, I assumed it's based on sd_batch_headers_skey like in last query.
dbfiddle demo
with t as (
select h.batch_id, h.parent_batch_id, l.batch_submission_date bs_date
from headers h
join lines l on l.sd_batch_headers_skey = h.sd_batch_headers_skey
and l.batch_line_number = '1' )
select batch_id, parent_batch_id,
coalesce(bs_date, (select bs_date from t x where x.batch_id = t.parent_batch_id)) bs_date
from t
where batch_id = 12345;
You could use simpler syntax with connect by and level <= 2 but if in your data there are really rows containing same ids (99999, 99999) then we get cycle error.

SQL LEFT() not working as expected when used with GROUP BY and Partition

I have codes that are like 1231231A, 1231231A, 3453454B etc
I need to group them by their number (ignoring the char which is a version) and just get one of each. I also need to drop the last char. My code works in grouping them and returning one of each, but it returns the last char.
Why is it returning the last char when i chop it off?
Expected output is
1231231
3453454
What I'm getting is
1231231A
3453454B
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY T.fldProductDescrip
ORDER BY T.fldEffectiveDate DESC) AS rn
FROM (
-- Insert statements for procedure here
SELECT JST.flduid
,JST.fldEffectiveDate
,(CASE
WHEN RIGHT(fldProductDescrip, 1) LIKE '[0-9]'
THEN fldProductDescrip
ELSE LEFT(fldProductDescrip, DATALENGTH(fldProductDescrip) - 1)
END) as fldProductDescrip
,(
CASE
WHEN PE.fldLogoutDateTime IS NULL
THEN PE.fldESigUser
ELSE ''
END
) AS LoggedIn
,(
CASE
WHEN PE.fldLogoutDateTime IS NULL
THEN PE.fldLoginDateTime
ELSE ''
END
) AS LoggedInDateTime
FROM tblJSJobSheetTemplates JST
INNER JOIN tblJSProducts JP ON JST.fldProductUID = JP.fldUID
INNER JOIN tblJSProductEsig PE ON JP.fldProductDescrip = PE.fldProduct
) AS T
WHERE LoggedIn <> ''
)AS G WHERE rn = 1

SQL Error - Column does not exist (in SELECT as)

I am joining two tables: breeds + breed_characteristics (bc)
But I'm getting the following error:
PG::UndefinedColumn: ERROR: column "val" does not exist LINE 11
I'm not sure what's wrong, here is my SQL:
SELECT
breeds.*,
CASE bc.user_val
WHEN NULL THEN bc.value
ELSE (bc.value + (bc.user_val/2))/2
END AS val
FROM
breed_characteristics bc
INNER JOIN breeds ON breeds.id = bc.breed_id
WHERE bc.characteristic_id = 45
AND val BETWEEN 4 AND 5
ORDER BY val DESC
(Executing this query on Postgres through Active Record)
You can't use expression alias val in where clause like that.
It's because there is an order in which SQL is executed specified in the SQL standard. Here, the WHERE clause is evaluated before SELECT and hence, the WHERE clause is not aware of the alias you created in the SELECT. The ORDER BY comes after the SELECT and hence can utilize aliases.
Just replace the alias with the actual case expression like this:
SELECT
breeds.*,
CASE bc.user_val
WHEN NULL THEN bc.value
ELSE (bc.value + (bc.user_val/2))/2
END AS val
FROM
breed_characteristics bc
INNER JOIN breeds ON breeds.id = bc.breed_id
WHERE bc.characteristic_id = 45
AND CASE WHEN bc.user_val is NULL THEN bc.value
ELSE (bc.value + (bc.user_val/2))/2
END BETWEEN 4 AND 5
ORDER BY val DESC
However, you can use alias in order by clause.
One option to avoid restating the CASE expression in multiple places is to use a subquery:
SELECT *
FROM
(
SELECT b.*,
bc.characteristic_id,
CASE WHEN bc.user_val IS NULL THEN bc.value
ELSE (bc.value + (bc.user_val / 2)) / 2
END AS val
FROM breed_characteristics bc
INNER JOIN breeds b
ON breeds.id = bc.breed_id
) t
WHERE t.characteristic_id = 45 AND
t.val BETWEEN 4 AND 5
ORDER BY t.val DESC

How to implement a SQL Server query which has several join conditions

I am trying to implement this query but I can’t figure out why I am not getting the result.
Here are the descriptions:
Lets say I have a table call: TableAct
Acct# Date WithdrawAmt DepositAmt
!24455 2012-11-19-00.00.00 1245.77 200.50
125577 2011-02-12-00.00.00 100.98 578.00
Another table TableCustomerOrd:
ID# COrder# CustID Ord_Description VendorType
124455 7712AS 123 1AAA Permanent
125577 9914DL 346 1BBB Partial
... UK1234 111 2HJ5 Permanent'
,,, FR0912 567 5LGY Partial
Then TableCustomerDtls:
CustID Descriptions Delivery Address ZipCode
123 1AAA_BLUESHARE SUCCESSFUL 222 Main St 97002
346 1BBB_CHASE DECLINE 40 West Side 97122
111 2HJ5_CITIBANK SUCCESSFUL ……. …….
567 5LGY_VANGURD DECLINED ---- -----
And table DelivaryFlight:
FlightOrder# FlightCustID FlightDt
7712AS 123 2011-9-29-00.00.00
9914DL 346 2010-11-2-00.00.00
UK1234 111 2012-4-1-00.00.00
FR0912 567 2012-9-11-00.00.00
I want to update TableAct on the following conditions:
TableAct. Acct# = TableCustomerOrd.ID#, AND:
TableCustomerOrd. CustID = TableCustomerDtls.CustID and at the same time, TableCustomerOrd.Ord_Descriptions field should match with TableCustomerDtls. Descriptions field anything before “_” . Therefore ‘1AAA’, ‘2HJ5’ etc. AND:
DelivaryFlight.FlightOrder# = TableCustomerOrd.COrder#, AND: DelivaryFlight.FlightCustID = TableCustomerOrd. CustID. Also TableCustomerDtls. Delivery = ‘SUCCESSFUL’ AND:
DelivaryFlight.FlightOrder# = TableCustomerOrd. COrder#
AND DelivaryFlight.FlightCustID = TableCustomerOrd. CustID
Also TableCustomerDtls. Delivery = ‘DECLINED
Then I want to compare: elivaryFlight.FlightDt > DelivaryFlight.FlightDt.
Basically I need to match table DelivaryFlight columns FlightOrder#, FlightCustID with TableCustomerOrd.
Moreover TableCustomerDtls column Delivery to ck for delivary status such as ‘DECLINED’.
And ‘SUCCESSFUL’ condition and compare ‘SUCCESSFUL’ FlightDt with ‘DECLINED’ FlightDt.
Here's my query but please help me to understand, I am sure this could be done in a better way.
The query is not working:
Update
Set …
FROM TableAct AC
Join TableCustomerOrd CustOd
ON AC.Acct# = CustOd.ID#
Join TableCustomerDtls CDtls
ON CDtls. CustID = CustOd. CustID
AND (CustOd.Ord_Descriptions =
Left(CDtls.Descriptions, LEN(rtrim(CDtls.Descriptions))))
JOIN DelivaryFlight DF
ON DF.FlightOrder# = CustOd.COrder#
AND DF.FlightCustID = CustOd.CustID
AND CDtls.Delivery = ‘SUCCESSFUL’
JOIN DelivaryFlight DF2
ON DF2.FlightOrder# = DF.COrder#
AND DF2.FlightCustID = DF.CustID
AND CDtls.Delivery = ‘DECLINED’
WHERE DelivaryFlight. FlightDt > DelivaryFlight. FlightDt
AND DepositAmt > 100
Your Help will be monumental 'cause my project due end of this week.
Thank you
If I have a complex query like this, I start by creating a "simple" select which produces only the rows to be updated.
It should also return both the update values and the pk for the updated table
It is then (relatively) straight forward to (inner) join this with the table to be updated and do the update remebering to only update matching rows by including
WHERE tblTobeUpdated.pk = SimpleSelect.pk
Hope this helps
I don't have the time to look at this in depth but I suspect you at least want to fix:
WHERE DelivaryFlight. FlightDt > DelivaryFlight. FlightDt
This is a condition that can never be met.
You probably want:
WHERE DF. FlightDt > DF2. FlightDt
it is also useful with these complex queires for an update to be able to see the records that would be updated, so I usually do something like this:
Update
Set …
--Select *
FROM TableAct AC
Then instead of running the update, I run just highlight and run the part that starts with select to see the results and don't test the update until I am sure I am selecting the records I want to select and that the values I will be replacing are correct.
Try breaking your query down, heres a query I wrote today, test each part separately
SELECT
Employee
, Reference
, Payroll
, [Hours] / 60
[Hours]
, [Days]
FROM
(
SELECT
Employee
, Reference
, Payroll
, SUM( Duration ) AS [Hours]
, AvailableID
FROM
(
SELECT
RequirerID
, Duration
, RTRIM( COALESCE(MA.MemberLastName, '')
+ ' ' + COALESCE(MA.MemberFirstName, '')
+ ' ' + COALESCE(MA.MemberInitial, '')) Employee
, COALESCE(MA.Detailref1, '') Reference
, COALESCE(MA.PayrollRef, '') Payroll
, Available.AvailableId
FROM
(
SELECT DISTINCT
RequirerID
, ShiftDate
, CAST(ShiftStart - ShiftEnd - ShiftBreak AS DECIMAL(19,2)) ShiftDuration
, Id RequirementRecordID
FROM
Requirements
WHERE
Requirements.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND RequirerID IN (SELECT ID FROM MemberDetails WHERE CompanyID = #ParamCompanyID)
)
R
INNER JOIN
ShiftConfirmed
INNER JOIN
Available
INNER JOIN
MemberDetails MA
ON Available.AvailableID = MA.ID
ON ShiftConfirmed.AvailableRecordID = Available.ID
ON R.RequirementRecordID = ShiftConfirmed.RequirementRecordID
WHERE
R.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND COALESCE(ShiftChecked, 0) BETWEEN 0 AND 1
)
ShiftDay
Group By
Employee
, Reference
, Payroll
, AvailableId
) Shifts
INNER JOIN
(
SELECT
COUNT( * ) AS [Days]
, AvailableID
FROM
(
SELECT DISTINCT
R.ShiftDate
, Available.AvailableId
FROM
(
SELECT DISTINCT
ShiftDate
, Id RequirementRecordID
FROM
Requirements
WHERE
Requirements.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND RequirerID IN (SELECT ID FROM MemberDetails WHERE CompanyID = #ParamCompanyID)
)
R
INNER JOIN
ShiftConfirmed
INNER JOIN
Available
INNER JOIN
MemberDetails MA
ON Available.AvailableID = MA.ID
ON ShiftConfirmed.AvailableRecordID = Available.ID
ON R.RequirementRecordID = ShiftConfirmed.RequirementRecordID
WHERE
R.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND COALESCE(ShiftChecked, 0) BETWEEN 0 AND 1
)
ShiftDay
Group By
AvailableId
) D
ON Shifts.AvailableID = D.AvailableID
WHERE [Hours] > 0
ORDER BY
Employee