MySql query ordering - mysql

Here is my data. I want to take 6 rows, but I want all HeadlineCategoryId's to be unique in my result list. If I select the top 6 I would take 2 rows from HeadlineCategoryID 20 (6,2). Do you have any suggestions about it?

SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT HeadlineCategoryID, MAX(Creation) max_date
FROM TableName
GROUP BY HeadlineCategoryID
) b ON a.HeadlineCategoryID = b.HeadlineCategoryID AND
a.Creation = b.max_date
ORDER BY a.Creation DESC -- << specify here how are you going to sort
LIMIT 6 -- the records you want to get
UPDATE 1
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT HeadlineCategoryID, MAX(NewsID) max_id
FROM TableName
GROUP BY HeadlineCategoryID
) b ON a.HeadlineCategoryID = b.HeadlineCategoryID AND
a.NewsID = b.max_id
ORDER BY a.Creation DESC -- << specify here how are you going to sort
LIMIT 6 -- the records you want to get

It looks like you want the six most recent records, but unique by HeadlineCategoryId. If so, this will work:
select top 6 NewsId, Creation, HeadlineCategoryId
from (select t.*,
row_number() over (partition by HeadlineCategoryId order by Creation desc) as seqnum
from t
) t
where seqnum = 1
As a note . . . This question originally indicated that it was using SQL Server, not MySQL. The solution in MySQL is not as simple. Here is one method with not exists:
select NewsId, Creation, HeadlineCategoryId
from t
where not exists (select 1
from t t2
where t2.HeadlineCategoryId = t.HeadlineCategoryId and
t2.id < t.id)
limit 6
The not exists portion is saying "where there is no other record with a larger id for a given headline category".

Related

How to use a dynamic limit in sql query

I have a query SELECT * FROM grades WHERE userid = 4123;
I want to limit this query
I have a query SELECT * FROM grades WHERE userid = 4123 LIMIT(2);
This works great but if I want this limit to be dynamic from another query.
SELECT COUNT(id) FROM count_table WHERE course = 131;
doing this gives me a syntax error
SELECT * FROM grades WHERE userid = 4123 LIMIT (SELECT COUNT(id) FROM count_table WHERE course = 131);
if this is not possible at all, then is there an alternative way to achieve this?
please help.!
You can do it in MySQL 8.x using the ROW_NUMBER() function.
Assuming you order the rows by some column (I guessed the column ID... change it as needed), you can do:
select
g.*
from (
select
*,
row_number() over(order by id) as rn -- change ordering as needed
from grades
) g
join (
SELECT COUNT(id) as cnt FROM count_table WHERE course = 131
) c on g.rn <= c.cnt

Particular MySql Query

Having the following tables
Post(*id, name, description, cat, publish_date)
Category(*id, name)
It is possible in ONE query to get (max) the first N element of each different category?
Assuming that N=3, i'd need the following result:
Result set:
["1", "Name1","Descr","cat1"]
["2", "Name1","Descr","cat1"]
["3", "Name1","Descr","cat1"]
["10","Name1","Descr","cat2"]
["20","Name1","Descr","cat2"]
["22","Name1","Descr","cat2"]
["25","Name1","Descr","cat3"]
["30","Name1","Descr","cat3"]
["19","Name1","Descr","cat3"]
And so on.
I need this, to get the first N article of EACH category, with one query (so without ask for a specific category but for all category in table)
It is possible? If yes what's the right query?
This query will do what you need. If any category has less than 3 post it will still work.
SELECT P.id,P.name,P.description,C.name
FROM Post P
LEFT JOIN Category C
ON P.type = C.id
WHERE FIND_IN_SET(P.id,
(
SELECT GROUP_CONCAT(ids) FROM
(SELECT SUBSTRING_INDEX(GROUP_CONCAT(id),',',3) as ids
FROM Post
GROUP BY type
) AS foo
GROUP BY ''
)
)
Here is a working SQL Fiddle
UPDATE
In response to your comment and updated question:
SELECT P.id,P.name,P.description,P.publish_date,C.name
FROM Post P
LEFT JOIN Category C
ON P.type = C.id
WHERE FIND_IN_SET(P.id,
(
SELECT GROUP_CONCAT(ids) FROM
(SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY publish_date DESC),',',3) as ids
FROM Post
GROUP BY type
) AS foo
GROUP BY ''
)
)
You can use UNION to join multiple queries into one. This assumes that you know what type you are selecting for each set.
SELECT * FROM
(
SELECT * FROM T1 WHERE type='Type1' ORDER BY id DESC LIMIT 3
) DUMMY1
UNION ALL
SELECT * FROM
(
SELECT * FROM T1 WHERE type='Type2' ORDER BY id DESC LIMIT 3
) DUMMY2
UNION ALL
SELECT * FROM
(
SELECT * FROM T1 WHERE type='Type3' ORDER BY id DESC LIMIT 3
) DUMMY3
The DUMMY table aliases are needed to allow ordering within each subquery.

mysql unique statement

I have a table like so
ID | date | CODE
1 01-02-13 VDOT
2 03-02-13 CMAX
3 05-02-13 VDOT
1 05-02-13 CMAX
1 09-02-13 VDOT
My SQL query is as follows
SELECT * FROM Table_Name ;
Which is obviously showing all the results but I need to only show one instance of each code where the date is most recent so my result needs to look like this
1 09-02-13 VDOT
1 05-02-13 CMAX
Can anyone tell me how how to only get one result for each code (the most recent entry by date)?
SELECT a.*
FROM TableName a
INNER JOIN
(
SELECT CODE, MAX(date) max_date
FROM TableName
GROUP BY CODE
) b ON a.Code = b.Code AND
a.date = b.max_date
try this:
SELECT * FROM Table_Name
GROUP BY CODE
ORDER BY date DESC
This will ORDER after it groups. hence gives out ORDERS within the grouped-results.
.
But now try this:
SELECT * FROM
(SELECT * FROM Table_Name ORDER BY date DESC) tx2
GROUP BY CODE
This will ensure correct date ORDER before GROUP.
SELECT * FROM
TABLE AS A
JOIN
(
SELECT D.CODE, MAX(D.DATE) AS DATE FROM TABLE AS D
GROUP BY D.CODE
) AS E
WHERE
A.CODE = E.CODE
AND A.DATE = E.DATE

How to use distinct and limit together

I have a mysql query. I need to get last value from columns Lat,Lng from my table but serial_number column needs to be distinct.
How to make such a query?
This is needed as I am using this coordinates to load it to Google map. So when the Google maps loads I need to have a marker on each last coordinates where vehicle is.
SELECT m.*
FROM (
SELECT DISTINCT serial_number
FROM mytable
) md
JOIN mytable m
ON m.id =
(
SELECT id
FROM mytable mi
WHERE mi.serial_number = md.serial_number
ORDER BY
mi.time DESC, mi.id DESC
LIMIT 1
)
Create an index on (serial_number, time, id) for this to work fast.
If you want to retrieve the last record for a certain serial_number, just use this:
SELECT *
FROM mytable
WHERE serial_number = :my_serial_number
ORDER BY
time DESC, id DESC
LIMIT 1
1#
Assuming that max ID will always give you last lat and lon, the query becomes quite simple -
SELECT t2.*
FROM table t2
where t2.id IN
(
SELECT max(t1.id)
FROM table t1
GROUP BY t1.serial_number
)
2#
If you need to consider time also, then you will need to do it this way. Here, in the inner query, max_time of each serial_number is obtained. Then this max_time and serial_number is joined with the outer table time and serial_number respectively, to get distinct records with last lat and lon.
SELECT *
FROM table t2,
(
SELECT max(t1.time) max_time, t1.serial_number
FROM table t1
GROUP BY t1.serial_number
) new_table
WHERE t2.time=new_table.max_time
AND t2.serial_number=new_table.serial_number
Try this
select distinct serial_number, *
from table t
inner join table t1 on t1.serial_number = t.serial_number and t1.id = (select max id from table t2 where t2.serial_number = t1.serial_number)

MySQL - Using COUNT(*) in the WHERE Clause?

Ok so I want to find all the rows with the same value in. (Or at least a pair)
I.E.
James| 19.193.283.19
John| 20.134.232.344
Jack| 19.193.283.19
Jonny| 19.193.283.19
I would want it to return rows James, Jack and Jonny -as more than one row has the IP '19.193.283.19' in it.
I tried doing what the other similar question answered:
select *
from `Zombie`
group by `Ip`
having count(*) > 1
order by `Ip` desc
But it just returned 1 row with a pair or more of the similar 'Ip' I want every row.
How would I modify the SQL so it returns all indisinct rows?
Thanks alot.
You could use an exists subquery to find all rows that have a matching row with the same Ip:
select *
from YourTable as yt1
where exists
(
select *
from YourTable as yt2
where yt1.name <> yt2.name
and yt1.Ip = yt2.Ip
)
Sorting by the number of rows with the same Ip can be done with a self-join, like:
select yt1.name
, yt1.Ip
from YourTable as yt1
join YourTable as yt2
on yt1.name <> yt2.name
and yt1.Ip = yt2.Ip
group by
yt1.name
, yt1.Ip
order by
count(yt2.name) desc
Another way would be to join your table with the subquery you already have used (to find ips existing in more than one row):
SELECT t.name
, t.Ip
FROM
YourTable AS t
JOIN
( SELECT Ip
, COUNT(*) AS cnt
FROM YourTable
GROUP BY Ip
HAVING COUNT(*) > 1
) AS td
ON td.Ip = t.Ip
ORDER BY
td.cnt DESC
, t.Ip
, t.name