I am looking for some help with optimizing the below. Is there a method if Redshift that can be used to eliminate the need to call the sub select each time since they are virtually the same for different fields:
select
IdText AS EquipmentPointCode,
OnRLT AS Downtime,
( SELECT OnRLT FROM temp_pointsvr_uptime_dataset WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OnRLT > t1.OnRLT ORDER BY OnRLT ASC LIMIT 1) AS Uptime,
( SELECT LineDefault_Value1 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value1,
( SELECT LineDefault_Value2 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value2,
( SELECT LineDefault_Value3 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value3,
( SELECT LineDefault_Value4 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value4,
( SELECT LineDefault_Value5 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value5,
( SELECT LineDefault_Value6 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value6,
( SELECT LineDefault_Value7 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value7,
( SELECT StateDefault_Value1 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS StateDefault_Value1,
( SELECT StateDefault_Value2 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS StateDefault_Value2,
( SELECT StateDefault_Value3 FROM temp_not_pointsvr_downtime WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS StateDefault_Value3,
'FM 10' AS Equipment
FROM temp_pointsvr_downtime t1
WHERE IdText = (select IDtext from list_of_ids where rownum =1)
I feel like what you're trying to do can be accomplished using case statements, but without seeing an example of the tables/data you're working with it's tough to determine.
Tackling just the nested select statements, you should be able to use a common table expression to hit the table one time, instead of re-selecting from it each time:
WITH
id_text_filter AS (
SELECT IDtext
FROM list_of_ids
WHERE rownum = 1
)
SELECT
IdText AS EquipmentPointCode,
OnRLT AS Downtime,
( SELECT OnRLT FROM temp_pointsvr_uptime_dataset WHERE IdText = (select IDtext from list_of_ids where rownum =1) AND OnRLT > t1.OnRLT ORDER BY OnRLT ASC LIMIT 1) AS Uptime,
( SELECT LineDefault_Value1 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value1,
( SELECT LineDefault_Value2 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value2,
( SELECT LineDefault_Value3 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value3,
( SELECT LineDefault_Value4 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value4,
( SELECT LineDefault_Value5 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value5,
( SELECT LineDefault_Value6 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value6,
( SELECT LineDefault_Value7 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS LineDefault_Value7,
( SELECT StateDefault_Value1 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS StateDefault_Value1,
( SELECT StateDefault_Value2 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS StateDefault_Value2,
( SELECT StateDefault_Value3 FROM temp_not_pointsvr_downtime WHERE ti.IdText = f.IDtext AND OffRLT = t1.OnRLT ORDER BY ResetRLT DESC Limit 1) AS StateDefault_Value3,
'FM 10' AS Equipment
FROM temp_pointsvr_downtime t1
JOIN id_text_filter f ON ti.IDtext = f.IDtext
WHERE IdText = (SELECT IDtext FROM list_of_ids WHERE rownum =1)
Again, I'm not sure if this code will work straight out of the box, as I'm not able to test it. But the idea should be similar:
1) Create a common table expression with the data you want to use as a filter
2) Join to that table in the main SELECT
3) Define WHERE clauses based on an equality to the common table expression.
Related
I got a query
SELECT name AS name,
count(group_name) AS all_test_cases,
(SELECT count(*) FROM test_cases AS tc2 WHERE tc2.group_name = tg.name AND status = 'OK' ) AS passed_test_cases,
tg.test_value * (SELECT count(*) FROM test_cases AS tc2 WHERE tc2.group_name = name AND status = 'OK') AS total_value
FROM test_groups AS tg
LEFT JOIN test_cases AS tc
ON tg.name = tc.group_name
GROUP BY name, test_value
ORDER BY total_value DESC, name ASC
How I can replace duplicated subquery:
tg.test_value * (SELECT count(*) FROM test_cases AS tc2 WHERE tc2.group_name = name AND status = 'OK') AS total_value
with something more efficient in postgres without stored procedure?
Does this work for you?
with cte_test_cases as (
SELECT group_name,
count(*) filter (where status = 'OK') as passed_test_cases,
count(*) as all_test_cases
FROM test_cases
GROUP BY group_name
)
SELECT tg.name,
tc.all_test_cases,
tc.passed_test_cases,
tg.test_value * tc.passed_test_cases AS total_value
FROM test_groups AS tg
LEFT JOIN cte_test_cases AS tc
ON tg.name = tc.group_name
ORDER BY total_value DESC, name ASC
I define a field called a.onhold_endtime in the below code. I want to return that value as part of overall SELECT statement, but when I include it the alias a.* is not recognised. It returns an error "ERROR: missing FROM-clause entry for table "a" "
Select distinct
woas.workorderid,
a.onhold_endtime,
(SELECT
(SELECT count(*) AS work_hours
FROM generate_series (b.onhold_starttime
, a.onhold_endtime - interval '1h'
, interval '1h') h
WHERE EXTRACT(ISODOW FROM h) < 6
AND h::time >= '08:00'
AND h::time <= '18:00')
FROM (
SELECT DISTINCT woas.workorderid,
timestamp 'epoch' +
nth_value(wos.endtime,1) OVER(PARTITION BY woas.workorderid ORDER BY wos.endtime ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
/1000 * INTERVAL '1 second' as onhold_endtime from wo_status_info wos
LEFT JOIN wo_assessment woas ON woas.assessmentid = wos.assessmentid
WHERE tmp.workorderid = woas.workorderid AND wos.statusid = 1 AND wos.nextstatusid = 2
) as a
LEFT JOIN (
SELECT DISTINCT woas.workorderid,
timestamp 'epoch' +
nth_value(wos.endtime,1) OVER(PARTITION BY woas.workorderid ORDER BY wos.endtime ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
/1000 * INTERVAL '1 second' as onhold_starttime from wo_status_info wos
LEFT JOIN wo_assessment woas ON woas.assessmentid = wos.assessmentid
WHERE
(wos.statusid = 2 AND wos.nextstatusid <> 2)
) as b ON a.workorderid = b.workorderid) AS onhold_difference1
FROM wo_assessment as tmp
LEFT JOIN wo_assessment woas ON tmp.assessmentid = woas.assessmentid
LEFT JOIN wo_status_info wos ON woas.assessmentid = wos.assessmentid
ORDER BY woas.workorderid ASC
Is there a way I can structure the code so I can include items using the "a" alias?
Update with simplified code
I define a value called "onhold_endtime" within a subquery with an alias of "a". I would like to return the value a.onhold_endtime in my main SELECT statement
Select distinct
woas.workorderid,
a.onhold_endtime,
(SELECT
(SELECT count(*))
FROM (
SELECT DISTINCT woas.workorderid,
nth_value(wos.endtime,1) OVER(PARTITION BY woas.workorderid ORDER BY wos.endtime ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
as onhold_endtime from wo_status_info wos
WHERE y.workorderid = woas.workorderid AND wos.statusid = 1 AND wos.nextstatusid = 2
) as a
LEFT JOIN (
SELECT DISTINCT woas.workorderid,
nth_value(wos.endtime,1) OVER(PARTITION BY woas.workorderid ORDER BY wos.endtime ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
as onhold_starttime from wo_status_info wos
WHERE
(wos.statusid = 2 AND wos.nextstatusid <> 2)
) as b ON a.workorderid = b.workorderid) AS x
FROM wo_assessment as y
LEFT JOIN wo_assessment woas ON y.assessmentid = woas.assessmentid
In short - you can use outer query alias in correlated subquery:
t=# select o.oid, (select o.datname||'*') from pg_database o limit 1;
oid | ?column?
-------+-----------
13505 | postgres*
(1 row)
but can't do the opposite:
t=# select b.*, (select o.datname||'*') b from pg_database o limit 1;
ERROR: missing FROM-clause entry for table "b"
LINE 1: select b.*, (select o.datname||'*') b from pg_database o lim...
^
the closest to the expected would be:
t=# select oid,b.* from pg_database o, LATERAL (select o.datname||'*') b limit 1;
oid | ?column?
-------+-----------
13505 | postgres*
(1 row)
I've been struggling with this but I'm not really good at tsql.
This is what I got, and I can't have the DateTime calculates all right. I'm getting the sum between A and B but not the total sum. For example in the last column I have a 0 which is getting me back to -x.
Here is the procedure, and some of the data are like this:
Code_Procedure date_evenement codes_situation
---------------------------------------------------------------
000079500000 2013-05-21 13:07:00.000 COMCFM
000079500000 2013-05-21 20:24:00.000 PCHCFM
000079500000 2013-05-22 09:58:00.000 PCHCFM
000079500000 2013-05-23 00:00:00.000 AARCFM
000079500000 2013-05-23 00:00:00.000 LIVCFM
000079600000 2013-05-21 13:07:00.000 COMCFM
000079600000 2013-05-21 20:24:00.000 PCHCFM
000079600000 2013-05-22 11:18:00.000 PCHCFM
000079600000 2013-05-23 00:00:00.000 AARCFM
000079600000 2013-05-23 00:00:00.000 LIVCFM
Here is the proc:
DECLARE #COMCFM TABLE(numero_colis VARCHAR(25), date_evenement DATETIME);
INSERT #COMCFM SELECT TOP(5) numero_colis, date_evenement FROM cartitem_colis_postaux_etats WHERE (code_situation = 'PCH' AND code_justification = 'CFM')
WHILE (SELECT COUNT(*) FROM #COMCFM) > 0
BEGIN
DECLARE #Colis TABLE(numero_colis VARCHAR(25), date_evenement DATETIME, code_situation_code_justification NVARCHAR(32));
INSERT #Colis SELECT numero_colis, date_evenement, code_situation + code_justification FROM cartitem_colis_postaux_etats WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM) ORDER BY numero_colis, date_evenement
;WITH CTE AS
(
Select DISTINCT
*
,ROW_NUMBER() OVER(PARTITION BY numero_colis ORDER BY date_evenement ASC) Rn FROM #Colis
),CTE1 AS
(
SELECT DISTINCT
A.*
,DATEDIFF(mi, B.date_evenement, A.date_evenement) AS DIFF
FROM CTE A INNER JOIN CTE B On B.Rn + 1 = A.Rn
UNION All
SELECT A.*, 0 FROM CTE A Where Rn = 1
)
SELECT
A.*
,ISNULL((
SELECT
A.DIFF + B.DIFF
FROM CTE1 AS B
WHERE A.numero_colis = B.numero_colis
AND A.Rn = B.Rn + 1), 0) AS Sums
FROM CTE1 AS a
ORDER BY numero_colis, Rn ASC
DELETE FROM #Colis
DELETE FROM #COMCFM WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM)
END
I'm not really sure what you would like to achieve. Do you need date differencies as a cummulated value? If you need this, change your BEGIN-END block of your stored procedure with this code
BEGIN
DECLARE #Colis TABLE(numero_colis VARCHAR(25), date_evenement DATETIME, code_situation_code_justification NVARCHAR(32));
INSERT #Colis SELECT numero_colis, date_evenement, code_situation + code_justification FROM cartitem_colis_postaux_etats WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM) ORDER BY numero_colis, date_evenement
;WITH CTE AS
(
SELECT DISTINCT
*,
ROW_NUMBER() OVER(PARTITION BY numero_colis ORDER BY date_evenement ASC) Rn
FROM #Colis
),CTE1 AS
(
SELECT A.*, 0 AS CummulatedDiff
FROM CTE A
WHERE Rn = 1
UNION ALL
SELECT DISTINCT A.*, B.CummulatedDiff + DATEDIFF(mi, B.date_evenement, A.date_evenement) AS CummulatedDiff
FROM CTE AS A INNER JOIN
CTE1 AS B ON B.Rn + 1 = A.Rn AND B.numero_colis = A.numero_colis
)
SELECT *
FROM CTE1 AS a
ORDER BY numero_colis, Rn ASC
DELETE FROM #Colis
DELETE FROM #COMCFM WHERE numero_colis = (SELECT TOP(1) numero_colis FROM #COMCFM)
END
I hope this takes you further to your goal.
Given the following SQL:
;WITH Results AS
(
SELECT ItemListID, Title,
ROW_NUMBER() OVER(ORDER BY ItemListID DESC) as intRow,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT * FROM Results
WHERE intRow BETWEEN #intStartRow AND #intEndRow
ORDER BY ItemListID DESC
SELECT #NumberOfResultsReturned = ##ROWCOUNT
I would like to set a parameter, #ActualNumberOfResults to the value of TOP(1) ActualNumberOfResults that is returned from the CTE.
I used the following, after the CTE, but seems repetitive:
SELECT #ActualNumberOfResults = COUNT(*)
FROM ItemData
WHERE CONTAINS(Title, #FTSSearchTerm )
AND WebsiteID=#WebsiteID
How can I accomplish this?
;WITH cte AS
(
SELECT ItemListID, Title,
CASE WHEN ROW_NUMBER() OVER(ORDER BY ItemListID DESC)
BETWEEN #intStartRow AND #intEndRow THEN 1
END AS NumberOfResultsReturned,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT #NumberOfResultsReturned = COUNT(NumberOfResultsReturned),
#ActualNumberOfResults = MAX(ActualNumberOfResults)
FROM cte
Demo on SQLFiddle
Visit check this link on the MSDN> http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/c774bb71-84c9-44ce-bfce-a256ecbf56ab
;WITH CTE1
AS (...)
SELECT * FROM CTE1
;WITH CTE2
AS (...)
SELECT * FROM CTE2
here your code
;WITH Results AS
(
SELECT ItemListID, Title,
ROW_NUMBER() OVER(ORDER BY ItemListID DESC) as intRow,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT * FROM Results
WHERE intRow BETWEEN #intStartRow AND #intEndRow
ORDER BY ItemListID DESC
SELECT #NumberOfResultsReturned = ##ROWCOUNT
;WITH Results1 AS
(
SELECT ItemListID, Title,
ROW_NUMBER() OVER(ORDER BY ItemListID DESC) as intRow,
COUNT(ItemListID) OVER() AS ActualNumberOfResults
FROM ItemData
WHERE FREETEXT(Title, #FTSSearchTerm)
AND WebsiteID = #WebsiteID
AND ContentTypeID = #ContentTypeID
AND GeoID2 = #GeoID
)
SELECT #ActualNumberOfResults = COUNT(*)
FROM Results1
I would like to get the top 10 data from a table which needs to be sorted in ascending order in a outer query. Below is the pseudocode of the query. What are the options other than using table valued functions?
select * from
(select top 10 tour_date
from tourtable
order by tour_date desc)
order by tour_date asc
Your query as written should work, you'd just need to alias the subquery:
select *
from (select top 10 tour_date from tourtable order by tour_date desc) t
order by tour_date asc
Another alternative, assuming SQL Server 2005+:
SELECT t.tour_date
FROM (SELECT tour_date, ROW_NUMBER() OVER(ORDER BY tour_date DESC) AS RowNum
FROM tourtable) t
WHERE t.RowNum <= 10
ORDER BY t.tour_date ASC
which could also be written with a CTE:
WITH cteRowNum AS (
SELECT tour_date, ROW_NUMBER() OVER(ORDER BY tour_date DESC) AS RowNum
FROM tourtable
)
SELECT tour_date
FROM cteRowNum
WHERE RowNum <= 10
ORDER BY tour_date ASC
Tested in a non-tsql context:
select * from (select tour_date from tourable order by tour_date desc limit 10) a order by tour_date asc