I have a table named conductor. I want to select latest records that date less than my_value.
+----+-----------+------+
| id | program | date |
+----+-----------+------+
| 1 | program 1 | 1 |
| 2 | program 1 | 3 |
| 3 | program 2 | 3 |
| 4 | program 1 | 5 |
| 5 | program 1 | 7 |
+----+-----------+------+
If we consider my_value is 4 then output will be:
+----+-----------+------+
| id | program | date |
+----+-----------+------+
| 2 | program 1 | 3 |
| 3 | program 2 | 3 |
+----+-----------+------+
How can I select records by SQL?
SELECT * FROM Conductor
WHERE `date` = (SELECT max(`date`) FROM Conductor
WHERE `date` < myvalue )
You can try a query like:
SELECT * FROM conductor
WHERE date = (SELECT date FROM conductor
WHERE date < my_value ORDER BY DESC limit 1);
This should give you what you are expecting!
SELECT * FROM Conductor
WHERE date IN (SELECT max(date) FROM Conductor
WHERE date < myvalue )
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,program VARCHAR(12) NOT NULL
,date INT NOT NULL
);
INSERT INTO my_table VALUES
(1 ,'program 1',1),
(2 ,'program 1',3),
(3 ,'program 2',3),
(4 ,'program 1',5),
(5 ,'program 1',7);
SELECT * FROM my_table;
+----+-----------+------+
| id | program | date |
+----+-----------+------+
| 1 | program 1 | 1 |
| 2 | program 1 | 3 |
| 3 | program 2 | 3 |
| 4 | program 1 | 5 |
| 5 | program 1 | 7 |
+----+-----------+------+
SELECT x.*
FROM my_table x
JOIN
( SELECT program
, MAX(date) max_date
FROM my_table
WHERE date < 4
GROUP
BY program
) y
ON y.program = x.program
AND y.max_date = x.date;
+----+-----------+------+
| id | program | date |
+----+-----------+------+
| 2 | program 1 | 3 |
| 3 | program 2 | 3 |
+----+-----------+------+
Related
I am trying to create a classifier model for a dataset, but I have too many distinct values for my target variable. If I run something like this:
Create or replace model `model_name`
options (model_type="AUTOML_CLASSIFIER", input_label_cols=["ORIGIN_AIRPORT"]) as
select DAY_OF_WEEK, ARRIVAL_TIME, ARRIVAL_DELAY, ORIGIN_AIRPORT
from `table_name`
limit 1000
I end up getting
Error running query
Classification model currently only supports classification with up to 50 unique labels and the label column had 111 unique labels.
So how can I select, for example, all rows that have one of the first 50 values of ORIGIN_AIRPORT?
Select * from “TABLE_NAME” as T1 left outer join (SELECT distinct
COLUMN_NAME from TABLE_NAME Order by COLUMN_NAME limit 50)as T2 on
T1.COLUMN_NAME=T2.COLUMN_NAME
This query will fetch you 50 distinct values in the inner query, then the outer query searches for those particular 50 distinct values using the T1.COLUMN_NAME=T2.COLUMN_NAME commands and returns all the records( it shows null for those not included in the 50 unique list)
Given a table of values (origin_airport), with unique identifiers (id) and date, find the minimum date for each unique value (origin_airport) to decide which N origin_airport values are to be returned.
Return all rows which match the first 3 unique origin_airport values (densely ranked, by min(date) per origin_airport).
Updated: to use columns that more closely match the model, with origin_airport and a date column for ordering.
Full working test case
The test data:
CREATE TABLE airportlogs (
origin_airport int
, id int primary key auto_increment
, date date DEFAULT NULL
);
INSERT INTO airportlogs (origin_airport) VALUES
( 1 )
, ( 1 )
, ( 8 )
, ( 8 )
, ( 8 )
, ( 7 )
, ( 7 )
, ( 6 )
, ( 5 )
, ( 4 )
, ( 3 )
, ( 3 )
, ( 7 )
, ( 7 )
, ( 1 )
, ( 8 )
, ( 3 )
, ( 1 )
;
-- Create some dates to use for ordering.
-- Ordering can be as complicated as we need.
UPDATE airportlogs SET date = current_date + INTERVAL +id DAY;
-- Intermediate calculation to show the MIN(date) per origin_airport
WITH nvals (origin_airport, mdate) AS (
SELECT origin_airport, MIN(date) AS mdate FROM airportlogs GROUP BY origin_airport
)
SELECT *
FROM nvals
ORDER BY mdate
;
+----------------+------------+
| origin_airport | mdate |
+----------------+------------+
| 1 | 2021-08-05 |
| 8 | 2021-08-07 |
| 7 | 2021-08-10 |
| 6 | 2021-08-12 |
| 5 | 2021-08-13 |
| 4 | 2021-08-14 |
| 3 | 2021-08-15 |
+----------------+------------+
-- Calculation of ordered rank for the unique origin_airport values
-- by MIN(date) per origin_airport.
WITH nvals0 (origin_airport, date, mdate) AS (
SELECT origin_airport
, date
, MIN(date) OVER (PARTITION BY origin_airport) AS mdate
FROM airportlogs
)
, nvals (origin_airport, date, mdate, r) AS (
SELECT origin_airport
, date
, mdate
, DENSE_RANK() OVER (ORDER BY mdate) AS r
FROM nvals0
)
SELECT *
FROM nvals
ORDER BY r, date
;
Result:
+----------------+------------+------------+---+
| origin_airport | date | mdate | r |
+----------------+------------+------------+---+
| 1 | 2021-08-05 | 2021-08-05 | 1 |
| 1 | 2021-08-06 | 2021-08-05 | 1 |
| 1 | 2021-08-19 | 2021-08-05 | 1 |
| 1 | 2021-08-22 | 2021-08-05 | 1 |
| 8 | 2021-08-07 | 2021-08-07 | 2 |
| 8 | 2021-08-08 | 2021-08-07 | 2 |
| 8 | 2021-08-09 | 2021-08-07 | 2 |
| 8 | 2021-08-20 | 2021-08-07 | 2 |
| 7 | 2021-08-10 | 2021-08-10 | 3 |
| 7 | 2021-08-11 | 2021-08-10 | 3 |
| 7 | 2021-08-17 | 2021-08-10 | 3 |
| 7 | 2021-08-18 | 2021-08-10 | 3 |
| 6 | 2021-08-12 | 2021-08-12 | 4 |
| 5 | 2021-08-13 | 2021-08-13 | 5 |
| 4 | 2021-08-14 | 2021-08-14 | 6 |
| 3 | 2021-08-15 | 2021-08-15 | 7 |
| 3 | 2021-08-16 | 2021-08-15 | 7 |
| 3 | 2021-08-21 | 2021-08-15 | 7 |
+----------------+------------+------------+---+
The final solution:
WITH min_date (origin_airport, date, mdate) AS (
SELECT origin_airport
, date
, MIN(date) OVER (PARTITION BY origin_airport) AS mdate
FROM airportlogs
)
, ranks (origin_airport, date, mdate, r) AS (
SELECT origin_airport
, date
, mdate
, DENSE_RANK() OVER (ORDER BY mdate) AS r
FROM min_date
)
SELECT *
FROM ranks
WHERE r <= 3
ORDER BY r, date
;
The final result:
+----------------+------------+------------+---+
| origin_airport | date | mdate | r |
+----------------+------------+------------+---+
| 1 | 2021-08-05 | 2021-08-05 | 1 |
| 1 | 2021-08-06 | 2021-08-05 | 1 |
| 1 | 2021-08-19 | 2021-08-05 | 1 |
| 1 | 2021-08-22 | 2021-08-05 | 1 |
| 8 | 2021-08-07 | 2021-08-07 | 2 |
| 8 | 2021-08-08 | 2021-08-07 | 2 |
| 8 | 2021-08-09 | 2021-08-07 | 2 |
| 8 | 2021-08-20 | 2021-08-07 | 2 |
| 7 | 2021-08-10 | 2021-08-10 | 3 |
| 7 | 2021-08-11 | 2021-08-10 | 3 |
| 7 | 2021-08-17 | 2021-08-10 | 3 |
| 7 | 2021-08-18 | 2021-08-10 | 3 |
+----------------+------------+------------+---+
There are a number of other solutions.
The poster didn't mention the logic for this ordering. But with the above window function behavior, that's trivial to specify.
I have a table with this data:
| name | type | score |
+------+------+-------+
| a | 1 | 15 |
+------+------+-------+
| b | 2 | 12 |
+------+------+-------+
| c | 1 | 17 |
+------+------+-------+
Now I must create a query to get count of each type and name of student which recieve maximum score.
This is my query :
select name , count(*) as count ,score ,type
group by type
and the result is:
| name | type | score | count |
+------+------+-------+--------+
| a | 1 | 15 | 2 |
+------+------+-------+--------+
| b | 2 | 12 | 1 |
+------+------+-------+--------+
but I expect this result:
| name | type | score | count |
+------+------+-------+--------+
| c | 1 | 17 | 2 |
+------+------+-------+--------+
| b | 2 | 12 | 1 |
+------+------+-------+--------+
SELECT x.*
, y.total
FROM my_table x
JOIN
( SELECT type
, MAX(score) score
, COUNT(1) total
FROM my_table
GROUP
BY type
) y
ON y.type = x.type
AND y.score = x.score;
I'm trying to make a query setting rank column by First and Second column. Like Rank over Partition which doesn't exist MySQL
For example,
From
+----+-------+--------+------+
| id | First | Second | Rank |
+----+-------+--------+------+
| 1 | a | 10 | |
| 2 | a | 9 | |
| 3 | b | 10 | |
| 4 | b | 7 | |
| 5 | a | 1 | |
| 6 | b | 1 | |
+----+-------+--------+------+
To
+----+-------+--------+------+
| id | First | Second | Rank |
+----+-------+--------+------+
| 1 | a | 10 | 3 |
| 2 | a | 9 | 2 |
| 3 | b | 10 | 3 |
| 4 | b | 7 | 2 |
| 5 | a | 1 | 1 |
| 6 | b | 1 | 1 |
+----+-------+--------+------+
The Rank doesn't continue. It starts from 1 again when it reaches the last value of 'a' of 'First' column.
And it's gotta be SET not SELECT.
I wouldn't mind using SELECT but my point is I'm not trying to retrieve data from Database but setting values.
Cheers in advance mates.
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,first CHAR(1) NOT NULL
,second INT NOT NULL
);
INSERT INTO my_table VALUES
(1,'a',10),
(2,'a',9),
(3,'b',10),
(4,'b',7),
(5,'a',1),
(6,'b',1);
SELECT id
, first
, second
, rank
FROM
( SELECT x.*
, CASE WHEN #prev = first THEN #i:=#i+1 ELSE #i:=1 END rank
, #prev:=first
FROM my_table x
, (SELECT #prev:=null,#i:=0) vars
ORDER
BY first
, second
, id
) a
ORDER
BY id;
+----+-------+--------+------+
| id | first | second | rank |
+----+-------+--------+------+
| 1 | a | 10 | 3 |
| 2 | a | 9 | 2 |
| 3 | b | 10 | 3 |
| 4 | b | 7 | 2 |
| 5 | a | 1 | 1 |
| 6 | b | 1 | 1 |
+----+-------+--------+------+
6 rows in set (0.00 sec)
Came up with a solution which I was looking for.
I'm not sure if these queries are completely safe but so far no harms.
SET #rank = 0, #First = ''
UPDATE 'Table' SET
rank = IF(#First = First, #rank:= #rank +1, #rank := 1 AND #First := First)
ORDER BY First ASC, Second;
One method is a correlated subquery. For rank() you can do:
select t.*,
(select count(*) + 1
from t t2
where t2.first = t.first and t2.second < t.second
) as rank
from t;
Ranks are tricky to handle with variables (dense_rank() and row_number() are simpler).
EDIT:
This is easy to turn into an update:
update t join
(select t.*,
(select count(*) + 1
from t t2
where t2.first = t.first and t2.second < t.second
) as new_rank
from t
) tt
on t.id = tt.id
set t.rank = tt.new_rank;
I'm looking to allow for a custom ordering logic through mySQL that allows the following data set:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 1 | A special place | 3 | 10 | |
| 2 | Another title | 5 | 12 | |
| 3 | Words go here | 1 | 15 | |
| 4 | A wonder | 2 | 8 | |
+----+-----------------+------------+-------+--+
To return an order that alternates, row by row, by popularity and then by views, so the return results look like:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 3 | Words go here | 1 | 15 | |
| 2 | Another title | 5 | 12 | |
| 4 | A wonder | 2 | 8 | |
| 1 | A special place | 3 | 10 | |
+----+-----------------+------------+-------+--+
Where you will see the first row returns the 'most popular', the second row returns the most views, the third row returns the second most popular, and the 4th row returns the 2nd most views.
Currently I'm gathering an entire table through mySQL twice, and then merging these results in PHP. This isn't going to cut it when the database is large. Is this possible in mysql at all?
I guess something along these lines could work. Consider the following:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,x INT NOT NULL
,y INT NOT NULL
);
INSERT INTO my_table VALUES
(1,3,10),
(2,5,12),
(3,1,15),
(4,2, 8)
(5,4, 1);
We can rank x and y in turn, and then arrange those ranks in a single list - so will have x1,y1,x2,y2,etc - but all rows will appear twice; once for the x rank and once for the y rank...
SELECT * FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) n
ORDER BY rank
+----+---+----+------+
| id | x | y | rank |
+----+---+----+------+
| 5 | 4 | 1 | 1 |
| 3 | 1 | 15 | 1 |
| 4 | 2 | 8 | 2 |
| 4 | 2 | 8 | 2 |
| 1 | 3 | 10 | 3 |
| 1 | 3 | 10 | 3 |
| 5 | 4 | 1 | 4 |
| 2 | 5 | 12 | 4 |
| 2 | 5 | 12 | 5 |
| 3 | 1 | 15 | 5 |
+----+---+----+------+
Now we can just grab the lowest rank for each id...
SELECT id
, x
, y
FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) m
GROUP
BY id,x,y
ORDER
BY MIN(rank);
+----+---+----+
| id | x | y |
+----+---+----+
| 3 | 1 | 15 |
| 5 | 4 | 1 |
| 4 | 2 | 8 |
| 1 | 3 | 10 |
| 2 | 5 | 12 |
+----+---+----+
Incidentally, this should be faster with variables - but I cannot make that solution work at present - senior moment, perhaps.
Suppose I have such a table:
+-----+---------+-------+
| ID | TIME | DAY |
+-----+---------+-------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 1 | 1 | 2 |
| 2 | 2 | 2 |
| 3 | 3 | 2 |
| 1 | 1 | 3 |
| 2 | 2 | 3 |
| 3 | 3 | 3 |
| 1 | 1 | 4 |
| 2 | 2 | 4 |
| 3 | 3 | 4 |
| 1 | 1 | 5 |
| 2 | 2 | 5 |
| 3 | 3 | 5 |
+-----+---------+-------+
I want to fetch a table which represents 2 IDs which got the largest sum of TIME within the last 3 days (means from 3 to 5 in a DAY column)
So the correct result would be:
+-----+---------+
| ID | SUM |
+-----+---------+
| 3 | 9 |
| 2 | 6 |
+-----+---------+
The original table is much larger and more complex. So i need a generic approach.
Thanks in advance.
And so I just learned that MySQL used LIMIT instead of TOP...
fiddle
CREATE TABLE tbl (ID INT,tm INT,dy INT);
INSERT INTO tbl (id, tm, dy) VALUES
(1,1,1)
,(2,2,1)
,(3,3,1)
,(1,1,2)
,(1,1,1)
SELECT ID
,SUM(SumTimeForDay) SumTimeFromLastThreeDays
FROM (SELECT ID
,SUM(tm) SumTimeForDay
FROM tbl
GROUP BY ID, dy
HAVING dy > MAX(dy) -3) a
GROUP BY id
ORDER BY SUM(SumTimeForDay) DESC
LIMIT 2
select t1.`id`, sum(t1.`time`) as `sum`
from `table` t1
inner join ( select distinct `day` from `table` order by `day` desc limit 3 ) t2
on t2.`da`y = t1.`day`
group by t1.`id`
order by sum(t1.`time`) desc
limit 2