Can I nest a select statement within an IF function in SQL? - sql

Using Teradata..
I want to write a query that joins table 1 and table 2 on item code to the location in table 2.
There are multiple locations per item code and potentially multiple item code entries per location depending on date. I'm only interested in the most recent item per location. To achieve this I've used a nested query to select the max date per both location and item number. I'm still returning more rows of data than anticipated and suspect it is due to some duplicate locations slipping through, potentially with two different item numbers.
I'm wondering if its possible to use the IF operator to say "If there are duplicate locations, choose the location with the more recent date"
Is this possible?
Here is what I have written so far:
SELECT t1.item_no, t1.date, t2.location, t2.date
FROM table 1 t1
JOIN table 2 t2 ON t1.item_no = t2.item_no
WHERE (t1.item_no, t1.date) IN
(
SELECT item_no, MAX(date)
FROM table 1
GROUP BY item_no
)
AND (t2.location, t2.date) IN
(
SELECT location, MAX(date)
FROM table 2
GROUP BY location
)

Change your query and use Subquery
SELECT t1.item_no, t1.date, t2.location, t2.date FROM
(
SELECT item_no, MAX(date) date
FROM table 1
GROUP BY item_no
) T1
JOIN
(
SELECT location, MAX(date) date
FROM table 2
GROUP BY location
) T2
ON t1.item_no = t2.location

Without knowing DBMS, a solution could be to use ROW_NUMBER(). I'm not sure if there's a preference for nested queries over say CTE but a solution w/ CTE could be:
WITH items AS (
SELECT
item_no
,date AS item_date
,row_number() OVER (PARTITION BY item_no ORDER BY date desc) as rn
FROM table1
),
locations AS (
SELECT
location
,item_no
,date AS location_date
,ROW_NUMBER() OVER(PARTITION BY item_no, location ORDER BY date desc) as rn
from table2
)
SELECT
t1.item_no
,t1.item_date
,t2.location
,t2.location_date
FROM items AS t1
JOIN locations AS t2 on t1.item_no = t2.item_no
AND t2.rn = 1
WHERE t1.rn = 1

Related

How to get Full Record with MAX as aggregate function

I have a table with schema (id, date, value, source, ticker). I wanted to get record having highest ID group by date in sql server
Example Data
ID|date|value|source|ticker
3|10-Dec-2017|10|a|b
1|10-Dec-2017|11|p|q
Below query works in Sqlite. Do we know if I can do same with SqlServer
select max(id), date, value, source, ticker from table group by date
Expected return:-
ID|date|value|source|ticker
3|10-Dec-2017|10|a|b
Also how I can do same operation on UNION of 2 tables with same schema.
You can use subquery :
select t.*
from table t
where id = (select max(t1.id) from table t1 where t1.date = t.date);
However, you can also use row_number() function :
select top (1) with ties *
from table t
order by row_number() over (partition by [date] order by id desc);
You can also do it like below :
select t1.* from table1 t1
join (
select max(id) as id, [date] from table1
group by [date]
) as t2 on t1.id = t2.id
SQL HERE

Maximum date row postgresql

I want to find out a rows which have maximum date by product,
I want to find out a maximum date of rows by product_id
I have tried a DISTINCT but can't succeed!
One canonical way of doing this is to use a subquery to identify the records corresponding to the maximum dates for each product ID, and then restrict the original table via an INNER JOIN.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT PRODUCT_ID, MAX(DATE) AS DATE
FROM yourTable
GROUP BY PRODUCT_ID
) t2
ON t1.PRODUCT_ID = t2.PRODUCT_ID AND
t1.DATE = t2.DATE
Another way to do this would be via a window function.
select * from (
SELECT *, row_number() over (partition by Product_ID order by date desc) r
FROM table
) T
WHERE T.r=1

sql query that partitions the data and orders by time and then returns only specific records within a partition

So what I mean exactly is: data is partitioned by name and ordered by date
I would like now to select only those rows in each partition which are coming after the row where NO is null and GENRE is null (after the rowNo 3 in case of the provided example)
So result of the query should return rowNo 4 and 5
Query used:
select
name, no, genre, date,
ROW_NUMBER() OVER(PARTITION BY name, genre ORDER BY date)
from
sourceTable
Assuming there is only one row per name where no and genre are null, you can use
select t1.*
from tablename t1
join tablename t2 on t1.name = t2.name and t2.no is null and t2.genre is null
where t1.date > t2.date
Why wouldn't you just do this?
select t.*
from (select name, no, genre, date,
ROW_NUMBER() OVER(PARTITION BY name, genre ORDER BY date) as rowno
from sourceTable
) t
where rowno > 3;

PostgreSQL Selecting Most Recent Entry for a Given ID

Table Essentially looks like:
Serial-ID, ID, Date, Data, Data, Data, etc.
There can be Multiple Rows for the Same ID. I'd like to create a view of this table to be used in Reports that only shows the most recent entry for each ID. It should show all of the columns.
Can someone help me with the SQL select? thanks.
There's about 5 different ways to do this, but here's one:
SELECT *
FROM yourTable AS T1
WHERE NOT EXISTS(
SELECT *
FROM yourTable AS T2
WHERE T2.ID = T1.ID AND T2.Date > T1.Date
)
And here's another:
SELECT T1.*
FROM yourTable AS T1
LEFT JOIN yourTable AS T2 ON
(
T2.ID = T1.ID
AND T2.Date > T1.Date
)
WHERE T2.ID IS NULL
One more:
WITH T AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Date DESC) AS rn
FROM yourTable
)
SELECT * FROM T WHERE rn = 1
Ok, i'm getting carried away, here's the last one I'll post(for now):
WITH T AS (
SELECT ID, MAX(Date) AS latest_date
FROM yourTable
GROUP BY ID
)
SELECT yourTable.*
FROM yourTable
JOIN T ON T.ID = yourTable.ID AND T.latest_date = yourTable.Date
I would use DISTINCT ON
CREATE VIEW your_view AS
SELECT DISTINCT ON (id) *
FROM your_table a
ORDER BY id, date DESC;
This works because distinct on suppresses rows with duplicates of the expression in parentheses. DESC in order by means the one that normally sorts last will be first, and therefor be the one that shows in the result.
https://www.postgresql.org/docs/10/static/sql-select.html#SQL-DISTINCT
This seems like a good use for correlated subqueries:
CREATE VIEW your_view AS
SELECT *
FROM your_table a
WHERE date = (
SELECT MAX(date)
FROM your_table b
WHERE b.id = a.id
)
Your date column would need to uniquely identify each row (like a TIMESTAMP type).

Getting latest data from SQL

I'm having trouble getting the latest data out of this.
I have a table with these data:
ItemId, ShipmentId, Date
Items can be shipped many times and a shipment can contain multiple items.
I need to get the latest shipment for every item.
Table looks like this:
11 12 2011-05-13
11 2 2011-07-01
12 2 2000-03-02
...
The result should be
11 2 2011-07-01
12 2 2000-03-02
I can't find a solution to be exclusive.
How can I get the latest shipment for every item?
Assuming you're working with a database engine that supports ranking functions, use a CTE or subquery to order the results:
;With OrderedItems as (
select ItemId,ShipmentId,Date,
ROW_NUMBER() OVER (PARTITION BY ItemId ORDER By Date desc) as rn
from ItemsTable
)
select * from OrderedItems where rn = 1
select t1.ItemId, t1.ShipmentId, t1.Date
from tab t1
join (
select ItemId, max(Date) as Date
from tab
group by ItemId
) t on t1.ItemId = t.ItemId and t1.Date = t.Date
Didn't test it, but this general idea should work:
SELECT * FROM YOUR_TABLE T1
WHERE
NOT EXISTS (
SELECT * FROM YOUR_TABLE T2
WHERE T1.ItemId = T2.ItemId AND T1.Date < T2.Date
)
In plain English: select rows such that there is no other row with the same ItemId but later Date.
you can use rank() also in CTE
;With Ordered as (
select ItemId,ShipmentId,dates,
rank() OVER ( PARTITION by itemID ORDER By dates desc) as DateRank
from ItemsTable
)
select * from Ordered where DateRank = 1