select with multiple condition MAX - sql

How to select data with multiple condition max
SELECT * FROM [TEMP_TBL]
WHERE "FLDR_NUM" =(SELECT MAX(FLDR_NUM)
FROM [TEMP_TBL]) AND "DNLD_DT" =(SELECT MAX(DNLD_DT)
FROM [TEMP_TBL)

you can use cte to reuse your max() value.
with cte(maxflr) as (
select max(fldr_num) as maxflr from TEMP_TBL
)select * from TEMP_TBL
cross apply cte
where "FLDR_NUM" = cte.maxflr and "DNLD_DT" = cte.maxflr

Related

Use row value from CTE in function

I'm trying to use row values from CTE expressions to pass to a function.
Something like:
WITH
start_number(x) as (VALUES(1)),
end_number(y) as (VALUES(10)),
z AS (SELECT * FROM generate_series(start_number.x, end_number.y))
SELECT z.*
What's the syntax?
Notes: start_number & end_number may be the result of a query, typically returning a single row.
You need to reference the two CTEs in the FROM clause:
WITH start_number(x) as (
VALUES(1)
), end_number(y) as (
VALUES(10)
)
SELECT *
FROM start_number, end_number, generate_series(start_number.x, end_number.y))
You can simplify that by using only a single CTE for the numbers:
WITH params(start_number, end_number) as (
VALUES (1, 10)
)
SELECT *
FROM params p, generate_series(p.start_number, p.end_number))
You need a from clause so you can get x and y:
WITH start_number(x) as (
VALUES (1)
),
end_number(y) as (
VALUES (10)
),
z AS (
SELECT gs.z
FROM start_number CROSS JOIN
end_number CROSS JOIN LATERAL
generate_series(start_number.x, end_number.y) gs(z)
)
SELECT z.*
FROM z;
Merely defining a CTE does not make it available to subsequent code and CTEs in the query. You need to include the CTE in a FROM clause.
In addition, you should be in the habit of naming the columns in CTEs. In your code z has a column with no name.
The above is one method. You could also use subqueries as well:
WITH start_number(x) as (
VALUES(1)
),
end_number(y) as (
VALUES(10)
),
z AS (
SELECT *
FROM generate_series((SELECT x FROM start_number), (SELECT y FROM end_number))
)
SELECT z.*
FROM z;
Here is a db<>fiddle.

SQL query or cursor?

I have a table with two different stamps. Let's call them oristamp and tarstamp. I need to find only the records that for the same oristamp have different tarstamps. It is possible to do that with a simple query? I think should be used a cursor but I'm not familiar with that. Any help?
I hope I understand the question. I am assuming you want all rows where more than 1 distinct value for tarstamp exists for each oristamp.
DECLARE #t table(tarstamp int, oristamp int)
INSERT #t values
(1,1),
(1,1),
(1,2),
(2,2)
;WITH CTE as
(
SELECT *,
max(tarstamp) over (partition by oristamp) mx,
min(tarstamp) over (partition by oristamp) mn
FROM #t
)
SELECT *
FROM CTE
WHERE mx <> mn
Use a sub-query to find oristamp values having at least two different tarstamp values. Join with that sub-query:
select t1.*
from tablename t1
join (select oristamp from tablename
group by oristamp
having count(distinct tarstamp) >= 2) t2 on t1.oristamp = t2.oristamp
You could count the number of different oristamps per tarstamp and select the rows that have tarstamps with more than one oristamp, E.g.:
SELECT *
FROM mytable
WHERE tarstamp IN (SELECT tarstamp
FROM mytable
GROUP BY tarstamp
HAVING COUNT(DISTINCT oristamp) > 1)
In your case, using MIN and MAX aggregate functions will perform better as COUNT(DISTINCT oristamp) > 1 adds complexity to the execution plan:
SELECT tarstamp
FROM mytable
GROUP BY tarstamp
HAVING MIN(oristamp) != MAX(oristamp)
Try using a simple join:
DECLARE #t table(tarstamp int, oristamp int)
INSERT #t values
(1,1),
(1,1),
(1,2),
(2,2)
SELECT t1.*
FROM #t t1
INNER JOIN #t t2
ON t1.oristamp = t2.oristamp
WHERE t1.tarstamp <> t2.tarstamp
Try this query, which will return all those combination which contain different oristamp.
select distinct z.*
from
( select oristamp, count(*) ct
from mytable
Group by oristamp
)z,
( Select oristamp, tarstamp, count(*) ct
from mytable
Group by oristamp, tarstamp
)y
Where z.oristamp =y.oristamp
And z.ct != y.ct

sql with clause within a with clause

can i do something like this :
with t as
(
with tt as
(
select * from table
)
SELECT * FROM tt
)
select * from t
i willing to perform some logic on output of inner with clause & than again do some operations on output of the outer with clause.
any help will be appreciated ...
Thanks
note :- its just some simplified query that will resolve my problem in my actual query, which have nested with clause
You can do something like this:
with t as
(
select * from table
),
tt as
(
select * from t
)
select * from tt
No, you cannot nest CTE (Common Table Expression) but you can chain them:
with t as
(
select * from table
),
tt as
(
select * from t
)
SELECT * FROM tt

Select more columns with MAX function

Need to find in databse max value, but then i need read other values in columns.
Can this be done with one SQL command or I have to use this two commands?
SELECT MAX(id) FROM Table;
SELECT * FROM Table WHERE id = $value;
where $value is variable from 1st command
select * from your_table
where id = (select max(id) from your_table)
or
select t1.* from your_table t1
inner join
(
select max(id) as mid
from your_table
)
t2 on t1.id = t2.mid
Probably the simplest way is:
select *
from t
order by id
limit 1
Or use top 1 or where rownum = 1 or whatever is the right logic for your database.
Note: this only returns one row. If you have duplicate such rows, then comparison to the maximum will give you all of them.
Also, if you are using a database that supports window functions:
select *
from (select t.*, row_number() over (order by id desc) as seqnum
from t
) t
where seqnum = 1;

How to get Original Rows filtered by a HAVING Condition?

What is the method in T-SQL to select the orginal values limited by a HAVING attribute. For example, if I have
A|B
10|1
11|2
10|3
How would I get all the values of B (Not An Average or some other summary stat), Grouped by A, having a Count (Occurrences of A) greater than or equal two 2?
Actually, you have several options to choose from
1. You could make a subquery out of your original having statement and join it back to your table
SELECT *
FROM YourTable yt
INNER JOIN (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
) cnt ON cnt.A = yt.A
2. another equivalent solution would be to use a WITH clause
;WITH cnt AS (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
)
SELECT *
FROM YourTable yt
INNER JOIN cnt ON cnt.A = yt.A
3. or you could use an IN statement
SELECT *
FROM YourTable yt
WHERE A IN (SELECT A FROM YourTable GROUP BY A HAVING COUNT(*) >= 2)
A self join will work:
select B
from table
join(
select A
from table
group by 1
having count(1)>1
)s
using(A);
You can use window function (no joins, only one table scan):
select * from (
select *, cnt=count(*) over(partiton by A) from table
) as a
where cnt >= 2