I have such a MYSQL table
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`screen_name` text NOT NULL,
`user_no` int(20) NOT NULL,
`avatar` text NOT NULL,
`name` varchar(50) NOT NULL,
`location` varchar(50) DEFAULT NULL
PRIMARY KEY (`id`)
I need to create an SQL query.
ORDER BY id DESC
GROUP BY screen_name
Get "name" and "screen_name" fields
id between $idmin and $idmax
I will compare the performance of nested query and JOIN query seperately.
Can you propose query words?
Thank you
Edit: For nested query I tried this:
SELECT `name`,`screen_name` FROM `mytable` WHERE `id` IN
(SELECT `id` FROM `mytable` WHERE `id` BETWEEN 100 AND 500 ORDER BY `id` DESC)
GROUP BY `screen_name`
I couldn't write for joined type.
Edit2: Say it I have such rows:
id=1, screen_name=mike, name=uk
id=2, screen_name=albert, name=usa
id=3, screen_name=ash, name=uk
id=4, screen_name=albert, name=new_zelland
I need to get results like this:
id=4
id=3
id=1
Your query should be in this format:
SELECT MAX(id) AS max_id, user_no, screen_name
FROM table_name
WHERE id BETWEEN $idmin AND $idmax
GROUP BY screen_name
ORDER BY MAX(id) DESC;
SQLFIDDLE DEMO HERE
or with sub-query:
SELECT a.id, a.name, a.screen_name
FROM example a
INNER JOIN (SELECT screen_name, MAX(id) id
FROM example
WHERE id BETWEEN 1 AND 4
GROUP BY screen_name
) b
ON a.screen_name = b.screen_name
AND a.id = b.id
ORDER BY a.id DESC;
SQLFIDDLE DEMO HERE
Related
Two tables are defined:
CREATE TABLE `users` (
`user_id` mediumint(6) unsigned NOT NULL AUTO_INCREMENT,
`score` tinyint(1) unsigned DEFAULT NULL,
PRIMARY KEY (`user_id`)
);
CREATE TABLE `online` (
`user_id` mediumint(6) unsigned NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
PRIMARY KEY (`user_id`)
);
How to combine the tables so that the result would be sorted by the score field from the largest to the smallest but at the top there were records with the value NULL?
This query does not sort the second sample:
(SELECT * FROM `online` JOIN `users` USING(`user_id`) WHERE `score` IS NULL)
UNION
(SELECT * FROM `online` JOIN `users` USING(`user_id`) WHERE `score` IS NOT NULL ORDER BY `score` DESC)
Use two keys in the sort:
SELECT *
FROM `online` o JOIN
`users`
USING (user_id)
ORDER BY (`score` IS NULL) DESC, Score DESC;
MySQL treats booleans as numbers in a numeric context, with "1" for true and "0" for false. So, DESC puts the true values first.
Incidentally, your version would look like it works if you used UNION ALL rather than UNION. However, it is not guaranteed that the results are in any particular order unless you explicitly have an ORDER BY.
The UNION incurs overhead for removing duplicates and in doing so rearranges the data.
Try:
select * from online join users using (user_id) order by ifnull(score, 10) desc;
You can use order by Nulls Last in the end of your sql to show nulls on the first.
You can try below -
select * from
(
SELECT *,1 as ord FROM `online` JOIN `users` USING(`user_id`) WHERE `score` IS NULL
UNION
SELECT *,2 FROM `online` JOIN `users` USING(`user_id`) WHERE `score` IS NOT NULL
)A ORDER BY ord asc,`score` DESC
I'm having two table:
CREATE TABLE `apps` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(191) NOT NULL COLLATE 'utf8mb4_unicode_ci',
PRIMARY KEY (`id`)
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
;
CREATE TABLE `downloads_stats` (
`app_id` INT(10) UNSIGNED NOT NULL,
`date` DATE NOT NULL,
`downloads` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`app_id`, `date`),
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
First is the list of my apps, the other stores the download number of each app. What is the best way to get 10 most downloaded apps ? I can do simple JOIN and then SUM and ORDER BY but is it the most efficient way?
Yes, I'd use LEFT JOIN with GROUP BY, e.g.:
SELECT a.id, a.name, SUM(ds.downloads) AS 'downloads'
FROM apps a LEFT JOIN downloads_stats ds ON a.id = ds.app_id
GROUP BY a.id, a.name
ORDER BY SUM(ds.downloads) DESC
LIMIT 10;
If you just want the app_id then JOIN is not needed, e.g.:
SELECT app_id, SUM(downloads) as 'downloaded'
FROM downloads_stats
GROUP BY app_id
ORDER BY SUM(downloads) DESC
Yes , you can use LEFT JOIN with GROUP BY
SELECT a.id , a.name , SUM(ds.downloads) AS 'downloads'
FROM apps a LEFT JOIN downloads_stats ds ON a.id = ds.app_id
GROUP BY a.id , a.name
ORDER BY downloads DESC
LIMIT 10;
I've a table in a DB that looks like this:
TABLE `partecipanti` (
`ID` int(11) NOT NULL,
`Name` varchar(30) DEFAULT NULL,
`Surname` varchar(30) DEFAULT NULL,
`Score2` int(11) DEFAULT NULL,
`Zero1` int(11) DEFAULT '0',
`Zero2` int(11) DEFAULT '0',
`Score1` int(10) NOT NULL DEFAULT '0'
)
And a query that looks like this:
SELECT *,Score1 + Score2 as Total FROM partecipanti
ORDER BY Total DESC,Score2 DESC,Zero2 DESC,Score1 DESC, Zero1 DESC;
Now the thing I'd like to do is : when I've a duplicate record (same name and same surname while the other data including ID are differents) pick the row that has the higher score which is stored in the field Total
I was thinking about a nested query,in the first query I order the data and I group them with GROUP BY, then I select the higher element. Could anyone help me please? Thanks.
EDIT:
If I add the DISTINCT statement the query seems to work , is it ok? Thanks.
You can try to run the following query and find the duplicates with max(id).
SELECT Score1, Score2, COUNT(*), Max(ID) AS dupes
FROM participanti
GROUP BY Total
HAVING (COUNT(*) > 1)
Given score2 can be null, try this:
select
p1.*
from
partecipanti p1
join ( select name, surname, max(score1 + coalesce(score2, 0) ) totalScore from partecipanti group by name, surname) p2 on
p1.Name = p2.Name and
p1.Surname = p2.Surname and
p1.score1 + coalesce(p1.score2, 0) = p2.totalScore
I have a table that contains many informations:
CREATE TABLE sequences (
`id` INT(11) NOT NULL DEFAULT '0',
`name` TEXT NULL,enter code here
`nbrlsu` BIGINT(20) NULL DEFAULT NULL,
`nbrits` BIGINT(20) NULL DEFAULT NULL,
`nbrco1` BIGINT(20) NULL DEFAULT NULL,
`nbrrcbl` BIGINT(20) NULL DEFAULT NULL,
`nbrmatk` BIGINT(20) NULL DEFAULT NULL,
`nbrsequences` BIGINT(20) NULL DEFAULT NULL,
`parent_id` BIGINT(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
I want to create a table based on sum of columns in the first table
for exemple I want to know te number of elements that have the same parent_id and has numbersequences>0
and I want to know for each type of sequences the number of rows that contains information:
SELECT parent_id ,
Classification,count(id) as nbrspecies,
SUM(nbrsequences) ,
SUM(nbrco1),
SUM(nbrits),
SUM(nbrlsu),
SUM(nbrrcbl),
SUM(nbrmatk)
FROM dashboard_specimen
GROUP BY parent_id
and I have an other kind of queries:
SELECT parent_id ,
count(id) as co1
FROM dashboard_specimen
WHERE nbrco1>0
GROUP BY parent_id ;
and
SELECT parent_id ,
count(id) as nbrspecies
FROM dashboard_specimen
WHERE nbrsequences>0
GROUP BY parent_id
and other types like this
and my goal in the end is to insert this information into an other table with insert select
like this:
INSERT INTO bold_namestats (id,
name,
numberofstrains,
numberofsequences,
numberofco1,
numberofits,
numberoflsu,
numberofrbcl,
numberofmatk)
SELECT parent_id ,
Classification,
count(id) as nbrspecies,
SUM(nbrsequences) ,
SUM(nbrco1),
SUM(nbrits),
SUM(nbrlsu),
SUM(nbrrcbl),
SUM(nbrmatk)
FROM dashboard_specimen
GROUP BY parent_id
I don't know if there is a simple way to do this with temp tables or something like this
If I understand well, you could do a subquery for each column you want to populate, filtering each subquery for an id.
INSERT INTO bold_namestats (id,
name,
numberofstrains,
numberofsequences,
numberofco1,
numberofits,
numberoflsu,
numberofrbcl,
numberofmatk)
select parent_id, (*select1* where parent_id=...), (*select2* where parent_id=...), ... , (*selectn* where parent_id=...)
from dashboard_specimen
group by parent_id
where select1, select2, ... , selectn are the different queries you have.
Finally I have resolved my problem using join and temp tables
INSERT INTO bold_namestats (_id,numberofstrains, numberofsequences,numberofco1,numberofits,numberoflsu,numberofrbcl,numberofmatk,numberstrainswithco1,numberstrainswithseq)
SELECT a._id ,a.numberofstrains,a.numberofsequences ,a.numberofco1,a.numberofits,a.numberoflsu,a.numberofrbcl,a.numberofmatk,b.numberofstrainswithco1,c.numberofstrainswithseq FROM bold_temp_namestats a left join bold_strainswithco1 b on a._id=b.parent_id left join bold_strainswithseq c on a._id=c.parent_id union
SELECT a._id ,a.numberofstrains,a.numberofsequences ,a.numberofco1,a.numberofits,a.numberoflsu,a.numberofrbcl,a.numberofmatk,b.numberofstrainswithco1,c.numberofstrainswithseq FROM bold_temp_namestats a right join bold_strainswithco1 b on a._id=b.parent_id left join bold_strainswithseq c on a._id=c.parent_id ;
this query is used to replace full outer join so I fill 3 tables with data and after that I insert with joinin result with left and right join and union the result to get full lines in the end
I have thus two tables:
CREATE TABLE `workers` (
`id` int(7) NOT NULL AUTO_INCREMENT,
`number` int(7) NOT NULL,
`percent` int(3) NOT NULL,
`order` int(7) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE `data` (
`id` bigint(15) NOT NULL AUTO_INCREMENT,
`workerId` int(7) NOT NULL,
PRIMARY KEY (`id`)
);
I want to return the first worker (order by order ASC) that his number of rows in the table data times percent(from table workers) /100 is smaller than number(from table workers.
I have tried this query:
SELECT workers.id, COUNT(data.id) AS `countOfData`
FROM `workers` as workers, `data` as data
WHERE data.workerId = workers.id
AND workers.percent * `countOfData` < workers.number
LIMIT 1
But I get the error:
#1054 - Unknown column 'countOfData' in 'where clause'
This should work:
SELECT A.id
FROM workers A
LEFT JOIN (SELECT workerId, COUNT(*) AS Quant
FROM data
GROUP BY workerId) B
ON A.id = B.workerId
WHERE (COALESCE(Quant,0) * `percent`)/100 < `number`
ORDER BY `order`
LIMIT 1
You could calculate the number of rows per worker in a subquery. The subquery can be joined to the worker table. If you use a left join, a worker with no data rows will be considered:
select *
from workers w
left join
(
select workerId
, count(*) as cnt
from data
group by
workerId
) d
on w.id = d.workerId
where coalesce(d.cnt, 0) * w.percent / 100 < w.number
order by
w.order
limit 1