oracle select statement reuse? - mysql

This is an extract sql that gets days
AND S.Date IN
(
SELECT Date
FROM
(
SELECT Date,
ROW_NUMBER() OVER (ORDER BY Date DESC )-1 Day
FROM CALENDAR_DIM
WHERE TYPE = 'ABC'
)
WHERE BUS_DAY BETWEEN 0 AND 2
)
I want to run this code twice in two parts of my sql. How can i do that without pasting the same code. Also .. how could i rewrite the above code?. I am having some issues with performance.

Solution 1 : use a WITH statement
WITH dateQuery AS (
SELECT Date
FROM
(
SELECT Date,
ROW_NUMBER() OVER (ORDER BY Date DESC )-1 BUS_DAY
FROM CALENDAR_DIM
WHERE TYPE = 'ABC'
)
WHERE BUS_DAY BETWEEN 0 AND 2)
SELECT xxx
FROM yyy
WHERE zzz
AND s.Date IN (SELECT Date FROM dateQuery)
The only part to repeat will then be
SELECT Date FROM dateQuery
Solution 2 : create a View
CREATE OR REPLACE VIEW V_DATE_QUERY AS
( SELECT Date
FROM
(
SELECT Date,
ROW_NUMBER() OVER (ORDER BY Date DESC )-1 BUS_DAY
FROM CALENDAR_DIM
WHERE TYPE = 'ABC'
)
WHERE BUS_DAY BETWEEN 0 AND 2)
and use it the same way
AND s.Date IN (Select Date FROM V_DATE_QUERY);

You would make this a view in your database like so:
CREATE VIEW view_date
AS
SELECT Date,
ROW_NUMBER() OVER (ORDER BY Date DESC )-1 Day
FROM CALENDAR_DIM
WHERE TYPE = 'ABC'
Now you can use:
AND S.Date IN
(
SELECT Date
FROM view_date
WHERE BUS_DAY BETWEEN 0 AND 2
)

Related

How to keep the latest record of a table

I have a table with following structure
Date
train
time1
train1
time2
train2
time3
train1
time4
train2
I want to create a new table and keeping only the latest record of each distinct train
Date
train
time3
train1
time4
train2
How should I achieve so?
One method is for selecting the most recent rows is:
select t.*
from releng_retry_test_phases t
where t.date = (select max(t2.date) from releng_retry_test_phases t2 where t2.train = t.train);
If you actually want to modify the table and delete the older rows;
delete t
from releng_retry_test_phases t join
(select t2.train, max(date) as max_date
from releng_retry_test_phases t2
group by t2.train
) t2
using (train)
where t.date < t2.max_date;
You can use ROW_NUMBER() to identify the rows you want:
select date, train
from (
select *,
row_number() over(partition by train order by date desc) as rn
) x
where rn = 1
WITH temp As(
SELECT *, Row_Number() over (PARTITION BY train ORDER BY date DESC ) as
rowNumber FROM table
)
SELECT date, train FROM temp WHERE rowNumber = 1
You can use row_number() method.

MySql last record from group by item_id with order by date

My database table name is ledgers and fields are id, item_id, date, ...other fields
I Want the last record from (groupBy item_id order by date ASC). from each group.
I tried below query
select
`id`,
`item_id`,
`date`,
`opening_quantity`,
`closing_quantity`,
`item_rate`,
`item_value`,
`previous_rate`
from `ledgers`
where date(`date`) >= ? and date(`date`) <= ?
group by `item_id`
order by `date` desc
Can you guys please help.
You can filter with a correlated subquery:
select t.*
from `ledgers` t
where
date(t.`date`) >= ?
and date(t.`date`) <= ?
and t.`date` = (
select max(t1.`date`)
from `ledgers` t1
where t1.`item_id` = t.`item_id`
)
For performance, consider an index on (item_id, date).
Another option is to use rank() (available in MySQ 8.0 only):
select *
from (
select
t.*,
rank() over(partition by `item_id` order by `date` desc) rn
from `ledgers` t
where date(t.`date`) >= ? and date(t.`date`) <= ?
) t
where rn = 1

SQL get Max Date

I need to have the last price for each product for each client . I am not really good with SQL and I don't understand how I can do it.
Data :
What I want :
It is possible to have this data with a SQL request ?
Use window function ROW_NUMBER(), if available in your RDBMS:
SELECT product, price, date, client
FROM (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY product, client ORDER BY date DESC) rn
FROM mytable t
) x
WHERE rn = 1
In MySQL < 8.0:
SELECT product, price, date, client
FROM mytable t
WHERE NOT EXISTS (
SELECT 1
FROM mytable t1
WHERE t1.client = t.client AND t1.product = t.product AND t1.date > t.date
)
One option could be a correlated subquery
SELECT product, price, date, client
FROM tablename a where date =
(select max(date) from tablename b where a.product=b.product)

mysqli UNION get data in correct column name

I want to get data from database with UNION , I defined link as newslink, and pic as articlepic but it show articlepic data under newslink column, how can I fix this?
SELECT * FROM
((SELECT date, link as newslink FROM news ORDER BY id DESC)
UNION
(SELECT date, pic as articlepic FROM article ORDER BY id DESC)) as x
ORDER BY date DESC LIMIT 6
Sample Data
I want to get articlepic data under articlepic column, and newslink under newslink column
if you values in different column you must add null value in the select for not corresponding columns
SELECT * FROM
((SELECT date, link as newslink, null as articlepic
FROM news ORDER BY id DESC)
UNION
(SELECT date, null, pic
FROM article ORDER BY id DESC)) as x
ORDER BY date DESC LIMIT 6
You are not able to get the different name of the column when using union in the query
SELECT * FROM
(
(
SELECT
DATE,
link AS newslink,
'-' As articlepic
FROM news ORDER BY id DESC
) UNION (
SELECT
DATE,
'-' As newslink,
pic AS articlepic
FROM article ORDER BY id DESC
)
) AS X
ORDER BY DATE DESC LIMIT 6

How to process multiple record with same id into single record with login / logout time in SQL?

is this possible to make a "newtable" from "oldtable" like a picture down below?
Use PIVOT method :
Declare #table table (id varchar(10),[time] time)
insert into #table
SELECT '01','10:08:23'
UNION ALL
SELECT '02','10:10:50'
UNION ALL
SELECT '01','13:30:00'
SELECT *
FROM
(
SELECT id , time , CASE WHEN MIN(RNo) = 1 THEN 'CheckIn' WHEN MAX(RNo) >
1 THEN 'CheckOut' END Type
FROM
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY id ORDER BY time) RNo
FROM #table
) A
GROUP BY id , time
) A
PIVOT
(
MAX(time) FOR Type IN ([CheckIn],[CheckOut])
)Pvt
This can be use for matching column (s)
INSERT INTO `NEWTABLE`(`id`, `check in`)
SELECT o.id, o.time FROM OLDTABLE o