Subquery Building a Column - sql

I am wondering if there is a more efficient way of doing the following query.
SELECT
t.iCertification_UserCertificationTranscriptID AS I_CERT_TRANSCRIPT_DIM,
t.iHR_UserID AS I_EMP_DIM,
t.iCertification_CertificationID AS I_RUL_CERT_DIM,
(
SELECT iHR_PositionID
FROM UserProfileNoGroups AS prof
WHERE
(iHR_UserID = t.iHR_UserID)
AND (Profile_IsPrimary = '1')
AND (UserPosition_IsPrimary = '1')
AND (t.dEffectiveStart BETWEEN UserPosition_Effective AND COALESCE(UserPosition_End, LOCALTIMESTAMP))
ORDER BY UserPosition_Effective DESC
FETCH FIRST 1 ROWS ONLY
) AS I_POSN_DIM,
CAST(EXTRACT(YEAR FROM t.dEffectiveStart) * 10000 + EXTRACT(MONTH FROM t.dEffectiveStart) * 100 + EXTRACT(DAY FROM t.dEffectiveStart) AS INT) AS I_DAY_STRT_DIM,
CAST(EXTRACT(YEAR FROM t.dEffectiveEnd) * 10000 + EXTRACT(MONTH FROM t.dEffectiveEnd) * 100 + EXTRACT(DAY FROM t.dEffectiveEnd) AS INT) AS I_DAY_END_DIM,
CASE
WHEN t.iCertification_TranscriptSourceID = '1' THEN 'Y'
ELSE 'N'
END AS L_AdminOverride,
t.mComment AS X_Comment
FROM
dbo.tCertification_UCT AS t;
I am concerned of the query that builds column I_POSN_DIM. The query performs slowly and it seems like that query has to be scanned over and over to extract results. This is in postgresql and I am not that familiar with this platform. I tried using CTEs that uses the MAX function, but the COUNT always turns out different from this query. Any assistance would be appreaciated.

I thought something like this:
SELECT
t.iCertification_UserCertificationTranscriptID AS I_CERT_TRANSCRIPT_DIM,
t.iHR_UserID AS I_EMP_DIM,
t.iCertification_CertificationID AS I_RUL_CERT_DIM,
uPG.iHR_PositionID AS I_POSN_DIM,
(t.dEffectiveStart.Year * 10000 + t.dEffectiveStart.Month * 100 + t.dEffectiveStart.Day) AS I_DAY_STRT_DIM,
(t.dEffectiveEnd.Year * 10000 + t.dEffectiveEnd.Month * 100 + t.dEffectiveEnd.Day) AS I_DAY_END_DIM,
CASE WHEN t.iCertification_TranscriptSourceID = '1' THEN 'Y' ELSE 'N' END AS L_AdminOverride,
t.mComment AS X_Comment
FROM dbo.tCertification_UCT AS t
INNER JOIN UserProfileNoGroups uPG ON t.iHR_UserID = uPG.iHR_UserID
WHERE Profile_IsPrimary = '1'
AND UserPosition_IsPrimary = '1'
AND (t.dEffectiveStart BETWEEN UserPosition_Effective AND COALESCE(UserPosition_End, LOCALTIMESTAMP));
I moved the inner query to outside and I convert it in an equivalent inner join. In others fields you did cast but it's not neccesary because of the result from that operations is an int.
But I supossed that table UserProfileNoGroups has 1 record for each record at tCertification_UCT. If it's not this way, the query would change a litlle:
SELECT
t.iCertification_UserCertificationTranscriptID AS I_CERT_TRANSCRIPT_DIM,
t.iHR_UserID AS I_EMP_DIM,
t.iCertification_CertificationID AS I_RUL_CERT_DIM,
uPG.iHR_PositionID OVER (ORDER BY UserPosition_Effective DESC) AS I_POSN_DIM,
(t.dEffectiveStart.Year * 10000 + t.dEffectiveStart.Month * 100 + t.dEffectiveStart.Day) AS I_DAY_STRT_DIM,
(t.dEffectiveEnd.Year * 10000 + t.dEffectiveEnd.Month * 100 + t.dEffectiveEnd.Day) AS I_DAY_END_DIM,
CASE WHEN t.iCertification_TranscriptSourceID = '1' THEN 'Y' ELSE 'N' END AS L_AdminOverride,
t.mComment AS X_Comment
FROM dbo.tCertification_UCT AS t
INNER JOIN UserProfileNoGroups uPG ON t.iHR_UserID = uPG.iHR_UserID
WHERE Profile_IsPrimary = '1'
AND UserPosition_IsPrimary = '1'
AND (t.dEffectiveStart BETWEEN UserPosition_Effective AND COALESCE(UserPosition_End, LOCALTIMESTAMP));
You can play with OVER clause:
https://www.postgresql.org/docs/9.1/tutorial-window.html

Related

Tuning the update statement in SQL Server or upgrade the query in T-SQL like Oracle plsql (for idx update)

Here is my update query in SQL Server, it is taking a long time to execute. I need help to re-write the query.
UPDATE d
SET d.CA_PAID_TO_DATE = s.canextpdate
FROM
(SELECT LTRIM(RTRIM(POLNUM)) POLNUM, CA_PAID_TO_DATE
FROM [DataAnalytics].[dbo].[tbla_hst_policy_history]
WHERE transmonth = '202112'
AND CA_PAID_TO_DATE IS NULL) AS d
INNER JOIN
(SELECT
LTRIM(RTRIM(CAPOLNUM)) CAPOLNUM,
CASE
WHEN LEFT(canextpdate, 2) > 85
THEN '19' + canextpdate
ELSE '20' + canextpdate
END canextpdate
FROM [DataAnalytics].[dbo].[tblh_lldca]
WHERE transmonth = '202112' ) AS s ON (d.POLNUM = s.CAPOLNUM);
Your rtrim() and ltrim() is completely questionable. You would be killing the use of indexes that way.
That one put aside, your statement is unnecessarily complex than what it needs to be. You could write it simpler and should be faster even in the existence of those ltrim(rtrim)()):
UPDATE d
SET CA_PAID_TO_DATE = CASE
WHEN LEFT(canextpdate, 2) > 85
THEN '19' + canextpdate
ELSE '20' + canextpdate
END
FROM
SELECT canextpdate
FROM [DataAnalytics].[dbo].[tblh_lldca] d
WHERE transmonth = '202112' and
exists (
SELECT * FROM [DataAnalytics].[dbo].[tbla_hst_policy_history] h
WHERE h.transmonth = '202112'
AND h.CA_PAID_TO_DATE IS NULL
AND LTRIM(RTRIM(h.CAPOLNUM)) = LTRIM(RTRIM(d.POLNUM))
);
Instead of ltrim(rtrim()), use a varchar\nvarchar field and fill with trimmed values once (and create index on that field).

BigQuery - Delete based on values from another table

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
)

How do i get result?

I need SUM of this result:
SELECT
ROUND(
(invoicesitems.pscost / invoicesitems.inmedunit -
AVG(ISNULL(mainexstock.peacecost,0)) / invoicesitems.inmedunit), 2)
*
CASE WHEN units.unitqty=3 THEN (invoicesitems.bigqty *
invoicesitems.inbigunit * invoicesitems.inmedunit) +
(invoicesitems.medqty * invoicesitems.inmedunit) +
invoicesitems.smallqty
ELSE (invoicesitems.bigqty * invoicesitems.inmedunit)
+ invoicesitems.smallqty
END AS PROFITS
FROM invoicesitems
INNER JOIN mainexstock ON mainexstock.pid = invoicesitems.pid
INNER JOIN units ON units.[uid] = invoicesitems.punits
WHERE invoicesitems.bid = 'B-0480580'
GROUP BY
invoicesitems.pid, invoicesitems.inbigunit,
invoicesitems.inmedunit, invoicesitems.bigqty,
invoicesitems.medqty, invoicesitems.smallqty,
invoicesitems.pscost, units.unitqty
You can use it as a CTE and get the sum. For example:
with a as (
-- your big query here
)
select sum(profits) as profits from a;

Postgresql group by error: more than one row returned by a subquery used as an expression

I have this table,
![enter image description here
I need to group them by address with 2 different rate 5 ride IDs and 2 different rate 1 ride IDs. The problem is I already tried so may ways but it always give me these type of errors in sql:
More than one row returned by a subquery used as an expression
Below is my query:
SELECT
e1.ride_id,
e1.rate,
concat(e1.service_date, ' ', e1.service_start) AS e1_timestamp_service_start,
concat(e1.service_date, ' ', e1.service_end) AS e1_timestamp_service_end,
e1.fare,
e1.trip_total_amount,
e1.actual_mileage,
e1.calc_mileage,
(SELECT e1.booked_pickup FROM efleet e1 GROUP BY e1.booked_pickup) as e1_booked_pickup,
e1.booked_dropoff,
e2.ride_id,
e2.rate,
concat(e2.service_date, ' ', e2.service_start) AS e2_timestamp_service_start,
concat(e2.service_date, ' ', e2.service_end) AS e2_timestamp_service_end,
e2.fare,
e2.trip_total_amount,
e2.actual_mileage,
e2.calc_mileage,
e2.booked_pickup,
e2.booked_dropoff,
e2.trip_total_amount - e1.trip_total_amount AS total_amount_difference,
e2.actual_mileage - e1.actual_mileage AS actual_mileage_difference
FROM efleet e1, efleet e2
WHERE EXTRACT(MONTH FROM e1.service_date) = 11
AND e2.service_date BETWEEN '2018-09-01' AND '2018-11-30'
AND e1.rate = '5'
AND e2.rate = '1'
AND e1.booked_trip_start_long = e2.booked_trip_start_long
AND e1.booked_trip_start_lat = e2.booked_trip_start_lat
AND e1.booked_trip_end_long = e2.booked_trip_end_long
AND e1.booked_trip_end_lat = e2.booked_trip_end_lat
AND e1.status = 'Approved'
AND e2.status = 'Approved'
AND e1.service_date = e2.service_date
AND e2.service_start BETWEEN (e1.service_start - '01:00:00') AND (e1.service_start + '01:00:00')
ORDER BY e1_booked_pickup;

Counting in a sql query

So I'm having a table like
Now I need to get this packed into a datagridview when a choice is made in a combobox filled with the uv ='owner'.
If I make a choice of the uv eg MG. I get a list of all his files/dosno he worked in and the times he spend working on the file.
I do this with this query :
SELECT kbpres.uv,
dbo.doss.dosno,
SUM(dbo.kbpres.uur) AS somuur,
SUM(dbo.kbpres.minuut) AS somminuut,
CAST (( SUM(dbo.kbpres.uur) + SUM(dbo.kbpres.minuut) / 60 ) AS VARCHAR(4)
) +
'u ' + CAST (( SUM(dbo.kbpres.minuut) % 60 ) AS VARCHAR(2)) + 'm' AS
[derivedColumn],
doss.behdr
FROM dbo.kbpres
INNER JOIN dbo.doss
ON dbo.kbpres.ino = dbo.doss.ino
WHERE ( dbo.kbpres.uv LIKE #cboBeheerder )
GROUP BY kbpres.uv,
dbo.doss.dosno,
doss.behdr
(Allthough I would only like to group by UV, and have to add the dosno and behdr as well ??)
The problem is now, how can I count the correct cost, as it is per record different.
for MG it would be :
10 * 60 for dosno 88888
20 * 76 for 66666
60*10 + (28hours+10minutes * 10) + 10*2 for 12345
Any idea if this is even possible ??
SELECT dosno,
SUM(uur)*60 + SUM(minuut) AS Time,
(SUM(uur)*60 + SUM(minuut)) * cost AS TotalCost
FROM dbo.kbpres k
INNER JOIN dbo.doss d ON k.ino = d.ino
GROUP BY dosno,k.ino,d.ino,cost
WHERE k.uv = 2
As cost seems to be a function of uv and dosno try
SELECT dosno,SUM(Time) AS Time,SUM(TotalCost) AS TotalCost FROM
(
SELECT dosno,
uur*60 + minuut AS Time,
(uur*60 + minuut) * cost AS TotalCost
FROM dbo.kbpres k
INNER JOIN dbo.doss d ON k.ino = d.ino
GROUP BY dosno,k.ino,d.ino,cost
WHERE k.uv = 2
) t
GROUP BY dosno