How to select specific rows in PostgreSQL query? - sql

I have written a query to get the 'reason_code' and 'app_count' for top five rows from result set and sum of remaining app_count under name 'others'.
Here what I have tried:
(SELECT a.app_pgm_rsnd_rsn_cd, a.denied_app_count
FROM (SELECT app_pgm_rsnd_rsn_cd ,COUNT(1) as denied_app_count
FROM app_pgm_choice, ead_case
where app_pgm_sts= 'DN'
AND app_pgm_req_dt >= '20150101'
AND app_pgm_req_dt <= '20150130'
AND EAD_CS_APP_NUM = APP_PGM_NUM
AND EAD_CS_SEND_CNTY_ID = '19'
AND EAD_CS_TRAN_STS = 'PE'
GROUP BY app_pgm_rsnd_rsn_cd
ORDER BY denied_app_count desc) a
WHERE ROWNUM <=5 )
UNION ALL
(SELECT 'OTHERS' as app_pgm_rsnd_rsn_cd, SUM(b.denied_app_count) as denied_app_count
FROM (SELECT app_pgm_rsnd_rsn_cd ,COUNT(1) as denied_app_count
FROM app_pgm_choice, ead_case
where app_pgm_sts= 'DN'
AND app_pgm_req_dt >= '20150101'
AND app_pgm_req_dt <= '20150130'
AND EAD_CS_APP_NUM = APP_PGM_NUM
AND EAD_CS_SEND_CNTY_ID = '19'
AND EAD_CS_TRAN_STS = 'PE'
GROUP BY app_pgm_rsnd_rsn_cd
ORDER BY denied_app_count desc) b
WHERE ROWNUM >=5 )
But when I run this query it shows following error message:
ERROR: column "rownum" does not exist
LINE 13: WHERE ROWNUM <=5 )
^
********** Error **********
ERROR: column "rownum" does not exist
SQL state: 42703
Character: 397
What is option for ROWNUM variable?

I think you are looking for the LIMIT clause.
SELECT *
FROM sometable
ORDER BY denied_app_count DESC
LIMIT 5
ROWNUM is an Oracle-ism.
For greater-than, you can use OFFSET:
SELECT *
FROM sometable
ORDER BY denied_app_count DESC
OFFSET 5
to skip the first 5 rows and return the rest.
The two can be, and often are, combined when doing things like pagination.
See LIMIT and OFFSET
In PostgreSQL you can use the row_number() window function, but for your purpose here it's unnecessary. On the other hand, it might be faster to do a single query with row_number then query the result table twice to get the two parts. Try that approach and see if it performs better.

Try this query
(SELECT a.app_pgm_rsnd_rsn_cd, a.denied_app_count
FROM (SELECT app_pgm_rsnd_rsn_cd ,COUNT(1) as denied_app_count
,row_number() OVER (ORDER BY app_pgm_rsnd_rsn_cd ) AS ROWNUM
FROM app_pgm_choice, ead_case
where app_pgm_sts= 'DN'
AND app_pgm_req_dt >= '20150101'
AND app_pgm_req_dt <= '20150130'
AND EAD_CS_APP_NUM = APP_PGM_NUM
AND EAD_CS_SEND_CNTY_ID = '19'
AND EAD_CS_TRAN_STS = 'PE'
GROUP BY app_pgm_rsnd_rsn_cd
ORDER BY denied_app_count desc) a
WHERE ROWNUM <=5 )
UNION ALL
(SELECT 'OTHERS' as app_pgm_rsnd_rsn_cd, SUM(b.denied_app_count) as denied_app_count
FROM (SELECT app_pgm_rsnd_rsn_cd ,COUNT(1) as denied_app_count
,row_number() OVER (ORDER BY app_pgm_rsnd_rsn_cd ) AS ROWNUM
FROM app_pgm_choice, ead_case
where app_pgm_sts= 'DN'
AND app_pgm_req_dt >= '20150101'
AND app_pgm_req_dt <= '20150130'
AND EAD_CS_APP_NUM = APP_PGM_NUM
AND EAD_CS_SEND_CNTY_ID = '19'
AND EAD_CS_TRAN_STS = 'PE'
GROUP BY app_pgm_rsnd_rsn_cd
ORDER BY denied_app_count desc) b
WHERE ROWNUM >=5 )

Related

Use of count in where statement sql

I have N transactions with camera_id = 6 and i want to sample every N // 100 transaction.
I have the following query:
SELECT t.id from (
SELECT id, camera_id, start_ts, ROW_NUMBER() OVER (ORDER BY start_ts) AS rownum
FROM transactions
WHERE camera_id = 6
) as t
where t.rownum % (N / 100) = 1
order by t.start_ts
How can i change it so i don't need additional query for determining N?
Untested
Does the following work for you - add a windowed count in addition to your Rownumber and use that:
SELECT t.id from (
SELECT id, camera_id, start_ts,
Row_Number() OVER (ORDER BY start_ts) AS rownum,
Count(*) over() Qty
FROM transactions
WHERE camera_id = 6
) as t
where t.rownum % (Qty / 100) = 1
order by t.start_ts

Mandt Specified Multiple Times But Not in Query

I get this error
Msg 8156, Level 16, State 1, Line 67
The column 'MANDT' was specified multiple times for 'cte'."
when attempting to run the code below however I am not including the column MANDT in my query. Both tables that I am calling do have a column MANDT, but they both have the column STAT as well and I did not have a problem with another table attempting the same join, the only thing is that table did not have MANDT, only STAT was the same.
I attempted to include both columns MANDT with an alias: JCDS_SOGR.MANDT as Client and TJ30T.MANDT as Client2 separately and together, this did not pan out. Got the same error message.
;WITH cte AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY STAT ORDER BY UDATE) AS Rn,
*,
LAG(UDATE) OVER (PARTITION BY STAT ORDER BY UDATE) AS PrevUDate,
COUNT(*) OVER (PARTITION BY STAT) AS [Count]
FROM
JCDS_SOGR
JOIN
TJ30T on JCDS_SOGR.STAT = TJ30T.ESTAT
WHERE
OBJNR = 'IE000000000010003137'
)
SELECT
MAX(rn) AS [Count],
OBJNR, STAT, TXT30,
SUM(CASE
WHEN rn % 2 = 0
THEN DATEDIFF(d, PrevUDate, UDATE)
WHEN rn = [Count]
THEN DATEDIFF(d, UDATE, GETDATE())
ELSE 0
END) AS DIF
FROM
cte
GROUP BY
OBJNR, STAT, TXT30
This is the other query I referred to that works fine with this same code.
;with cte
AS
(
select ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn
, *
, LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate
, COUNT(*) OVER(partition by STAT) As [Count]
from JCDS_SOGR
join TJ02T on JCDS_SOGR.STAT = TJ02T.ISTAT
where OBJNR = 'IE000000000010003137'
and TJ02T.SPRAS = 'E'
)
select Max(rn) As [Count]
, OBJNR,STAT,TXT30
, SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE)
WHEN rn=[Count] THEN DATEDIFF(d,UDATE,getDate())
ELSE 0 END) as DIF
from cte
group BY OBJNR, STAT,TXT30
The expected result is this
[COUNT OBJNR STAT TXT30 DIF
1 IE000000000010003137 I0099 Available 2810][1]
In your CTE, you are selecting *. So if you have two columns named MANDT, this could cause a conflict. Remove *. That should fix the problem that you described.

Getting ORA-00928: missing SELECT keyword error

I am getting an error
ORA-00928: missing SELECT keyword
while running this query:
WITH Dups AS
(
SELECT
ID, AMOUNT, BATCH_ID, PROCESS_DATE, ITEM_NUMBER, ERROR_TYPE, INSERTED_DATE,
ROW_NUMBER() OVER(PARTITION BY ID, ERROR_TYPE ORDER BY ID) AS rn
FROM
ERROR_TABLE
WHERE
inserted_date >= TRIM(TO_DATE('01-AUG-17', 'DD-MON-YY'))
AND inserted_date <= TRIM(TO_DATE('11-AUG-17', 'DD-MON-YY'))
)
DELETE FROM Dups
WHERE rn > 1
This is not how to delete duplicates in Oracle. Inspired, but not for that database. Something like this:
delete error_table et
where et.inserted_date >= date '2017-08-01' and
et.inserted_date <= date '2017-08-11' and
rowid > (select min(et2.rowid)
from error_table et2
where et2.inserted_date >= date '2017-08-01' and
et2.inserted_date <= date '2017-08-11' and
et2.id = et.id and
et2.error_type = et.error_type
);

Selecting 1 row per day closest to 4am? [duplicate]

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 6 years ago.
We're currently working on a query for a report that returns a series of data. The customer has specified that they want to receive 5 rows total, with the data from the previous 5 days (as defined by a start date and an end date variable). For each day, they want the data from the row that's closest to 4am.
I managed to get it to work for a single day, but I certainly don't want to union 5 separate select statements simply to fetch these values. Is there any way to accomplish this via CTEs?
select top 1
'W' as [RecordType]
, [WellIdentifier] as [ProductionPtID]
, t.Name as [Device Name]
, t.RecordDate --convert(varchar, t.RecordDate, 112) as [RecordDate]
, TubingPressure as [Tubing Pressure]
, CasingPressure as [Casing Pressure]
from #tTempData t
Where cast (t.recorddate as time) = '04:00:00.000'
or datediff (hh,'04:00:00.000',cast (t.recorddate as time)) < -1.2
order by Name, RecordDate desc
assuming that the #tTempData only contains the previous 5 days records
SELECT *
FROM
(
SELECT *, rn = row_number() over
(
partition by convert(date, recorddate)
order by ABS ( datediff(minute, convert(time, recorddate) , '04:00' )
)
FROM #tTempData
)
WHERE rn = 1
You can use row_number() like this to get the top 5 last days most closest to 04:00
SELECT TOP 5 * FROM (
select t.* ,
ROW_NUMBER() OVER(PARTITION BY t.recorddate
ORDER BY abs(datediff (minute,'04:00:00.000',cast (t.recorddate as time))) rnk
from #tTempData t)
WHERE rnk = 1
ORDER BY recorddate DESC
You can use row_number() for this purpose:
select t.*
from (select t.*,
row_number() over (partition by cast(t.recorddate as date)
order by abs(datediff(ms, '04:00:00.000',
cast(t.recorddate as time)
))
) seqnum
from #tTempData t
) t
where seqnum = 1;
You can add an appropriate where clause in the subquery to get the dates that you are interested in.
Try something like this:
select
'W' as [RecordType]
, [WellIdentifier] as [ProductionPtID]
, t.Name as [Device Name]
, t.RecordDate --convert(varchar, t.RecordDate, 112) as [RecordDate]
, TubingPressure as [Tubing Pressure]
, CasingPressure as [Casing Pressure]
from #tTempData t
Where exists
(select 1 from #tTempData t1 where
ABS(datediff (hh,'04:00:00.000',cast (t.recorddate as time))) <
ABS(datediff (hh,'04:00:00.000',cast (t1.recorddate as time)))
and GETDATE(t.RecordDate) = GETDATE(t1.RecordDate)
)dt
and t.RecordDate between YOURDATERANGE
order by Name, RecordDate desc;

SQL Server 2008 - Finding duplicates using ROW_NUMBER

i have the following SQL which works to find duplicates
SELECT *
FROM (SELECT
id,
ShipAddress,
ShipZIPPostal,
ROW_NUMBER() OVER (PARTITION BY shipaddress, shipzippostal ORDER BY shipaddress) ROWNUM
FROM orders
WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE())) x
WHERE rownum > 1
I would like to only see rows where, if the value of Rownum > 1 then i would like to see its corresponding row where rownum =1.
So basically, if a row has duplicates, i want to see the original row and all its duplicates.
If a row does not have duplicates, then i don't want to see it (it will have rownum = 1 )
How would i do this please?
cheers
Use count(*) rather than row_number():
SELECT *
FROM (SELECT id, ShipAddress, ShipZIPPostal,
COUNT(*) OVER (PARTITION BY shipaddress, shipzippostal) as cnt
FROM orders
WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE())
) x
WHERE cnt > 1;
In addition to Gordon's answer, if you want to keep the row_number() approach for some academic reason, you can do this:
SELECT *
FROM (SELECT
id,
ShipAddress,
ShipZIPPostal,
ROW_NUMBER() OVER (PARTITION BY shipaddress, shipzippostal ORDER BY shipaddress) ROWNUM
FROM orders
WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE())) x
WHERE EXISTS(
SELECT * FROM x x2
WHERE x.shipaddress=x2.shipaddress
AND x.shipzippostal=x2.shipzippostal
AND x2.ROWNUM>1
)
I'd actually prefer a cte structure like this personally:
WITH cte AS (
SELECT
id,
ShipAddress,
ShipZIPPostal,
ROW_NUMBER() OVER (PARTITION BY shipaddress, shipzippostal ORDER BY shipaddress) ROWNUM
FROM orders
WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE())
)
SELECT *
FROM cte
WHERE EXISTS(
SELECT * FROM cte x2
WHERE cte.shipaddress=x2.shipaddress
AND cte.shipzippostal=x2.shipzippostal
AND x2.ROWNUM>1
)
You could add a second row_number, but change the order by to ID so it will be different, and compare the 2 row_numbers
SELECT
*
FROM
(SELECT
id,
ShipAddress,
ShipZIPPostal,
ROW_NUMBER() OVER (PARTITION BY shipaddress,shipzippostal ORDER BY id) ROWNUM1,
ROW_NUMBER() OVER (PARTITION BY shipaddress,shipzippostal ORDER BY id DESC) ROWNUM2
FROM
orders
WHERE
CONVERT(DATE,orderdate) = CONVERT(DATE,GETDATE())
) x
WHERE
ROWNUM1 <> ROWNUM2