mysql DISTINCT() does not work as expected - mysql

I want to get list of posts sorted by number of comments, I've successfully ran following query but it gives repetitive values i.e posts repeat, I want unique of them sorted by number of comments, when I put DISTINCT() around my whole query, an error appears:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE(post.pname, post.pid FROM post, COMMENT WHERE post.pid = comment.pid ORD' at line 1
Query without DISTINCT() (Works but of course doesn't give unique values)
SELECT post.pname, post.pid
FROM post,
COMMENT WHERE post.pid = comment.pid
ORDER BY (
SELECT COUNT( * )
FROM COMMENT WHERE comment.pid = post.pid
GROUP BY post.pname
)
Query with DISTINCT() (doesn't work)
SELECT DISTINCT(post.pname, post.pid
FROM post,
COMMENT WHERE post.pid = comment.pid
ORDER BY (
SELECT COUNT( * )
FROM COMMENT WHERE comment.pid = post.pid
GROUP BY post.pname
))

DISTINCT should be used thus:
SELECT DISTINCT a,b,c FROM t;
without a GROUP BY. It will find all the (a,b,c) in the table, then de-dup them.
This is broken:
SELECT id, a, b FROM t GROUP BY id;
That is because it will find all the distinct values of id, but supply random values of a and b to go with each.
To find out how many of each foo there are, this pattern works nicely:
SELECT foo, COUNT(*) FROM t GROUP BY foo;
Don't use () after DISTINCT.
Since I don't understand what you are looking for, I may or may not have provided you enough info to fix your query. If I have failed, please provide some sample data and the desired output; sometimes reverse engineering is the easiest way to figure it out.

SELECT distinct(post.pname) FROM post,COMMENT WHERE post.pid = comment.pid ORDER BY (SELECT COUNT( * ) FROM COMMENT WHERE comment.pid = post.pid GROUP BY post.pname) DESC

SELECT post.pname, post.pid
FROM post
Inner Join ( Select
comment.pid
, COUNT(*) As Cant
From COMMENT
Group By
comment.pid
) As x
On post.pid = x.pid
ORDER BY x.Cant

SELECT p.*
FROM post p JOIN comment c ON c.postId = p.id
GROUP BY p.id
ORDER BY COUNT(*)

Related

SQLITE request syntax error

I have an issue with a request, it works fine with pgsql and mysql, but with sqlite, it seems like I am missing something
here is the request :
select * from mesure_insitu
where (id_formulaire, gid) IN (
select distinct id_formulaire, max(gid) as gid
from mesure_insitu
where id_dispo_comp_ouvr = 1
GROUP BY id_formulaire
ORDER BY id_formulaire ASC
)
This subquery below works fine:
select distinct id_formulaire, max(gid) as gid
from mesure_insitu
where id_dispo_comp_ouvr = 1
GROUP BY id_formulaire
ORDER BY id_formulaire ASC)
I think the problem is with the condition with two values (id_formulaire, gid), like sqlite cannot use a condition with two values.
I will appreciate any type of help.
To get this query to work, update your SQLite to a newer version.
If you cannot do this, you have to use a join instead:
SELECT *
FROM mesure_insitu
JOIN (SELECT id_formulaire, max(gid) AS gid
FROM mesure_insitu
WHERE id_dispo_comp_ouvr = 1
GROUP BY id_formulaire)
USING (id_formulaire, gid);
(The DISTINCT and ORDER BY are superfluous in this subquery.)

Error while compiling statement: FAILED: SemanticException [Error 10002]

select d.order_type from migu_td_aaa_order_log_d d where exists(select 1
from migu_user r where r.user_id = '156210106' and r.user_num =
d.serv_number) and d.product_id in ('2028594290','2028596512','2028597138' )
order by d.opr_time desc limit 1
why the above sql failed ,indicates :
FAILED: SemanticException [Error 10002]: Line 4:11 Invalid column reference 'opr_time'
but the below one works :
select temp.order_type from (
select d.* from migu_td_aaa_order_log_d d where exists(select 1 from
migu_user r where r.user_id = '156210106' and r.user_num = d.serv_number)
and d.product_id in ('2028594290','2028596512','2028597138' ) order by
d.opr_time desc limit 1) temp;
this one works fine ,too ,and much more efficient than the second one:
select d.* from migu_td_aaa_order_log_d d where exists(select 1 from
migu_user r where r.user_id = '156210106' and r.user_num = d.serv_number)
and d.product_id in ('2028594290','2028596512','2028597138' )
order by d.opr_time desc limit 1
I only need to get order_type field,so even though the second one works,but it cost much more time.
Can anyone help me?
Thanks a lot!
Your first query does not work because, in the first select statement, you are just getting one column (d.order_type), but you are trying to order by another column (d.opr_time), which you have not included in your select statement
select d.order_type from ...
...
order by d.opr_time desc limit 1
Note that if you added the column d.opr_time to your first query, it would work:
select d.order_type, d.opr_time from ...
...
order by d.opr_time desc limit 1
Your second query works because, in the subquery, you have selected all the columns of d (d.*), so when you order by opr_time, that column is present. (Same for the third query).
select temp.order_type from (
select d.* ... order by d.opr_time ...
EDITED:
According to the Hive documentation:
When using group by clause, the select statement can only include
columns included in the group by clause. Of course, you can have as
many aggregation functions (e.g. count) in the select statement as
well.
So, this query:
select d.order_type, d.opr_time from ...
...
order by d.opr_time desc limit 1
Shouldn't work either, because the select clause has an additional column (d.order_type) that is not included in the group by clause.
I hope this helps.
P.S. This answer about SQL execution order might be useful.
1.
Hive currently have an order by limitation.
The current status of this issue is PATCH AVAILABLE.
see -
"Can't order by an unselected column"
https://issues.apache.org/jira/browse/HIVE-15160
2.
You might want to get familiar with LEFT SEMI JOIN which is a cleaner syntax for EXISTS
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Joins#LanguageManualJoins-JoinSyntax
3.
using min / max over a struct / named_struct can be used instead of order by ... asc / desc and limit 1
Here is an alternative solution:
select max(named_struct('opr_time',d.opr_time,'order_type',d.order_type)).order_type
from migu_td_aaa_order_log_d d
left semi join migu_user r
on r.user_num =
d.serv_number
and r.user_id = '156210106'
where d.product_id in ('2028594290','2028596512','2028597138')
;
P.s.
You seriously want to consider to treat IDs (user_id, product_id) as numeric and not as strings.

Query returning false PHP

I am having trouble with a MySQL query. The query is as follows:
SET #catlocation = (SELECT id FROM categories WHERE url_name='hexcode');
SELECT
subs.display_name AS display,
subs.url_name AS url,
(
SELECT title
FROM threads
WHERE location = subs.id
ORDER BY time_submitted DESC
LIMIT 1
) AS title,
(
SELECT username
FROM users
WHERE uid = (
SELECT uid
FROM threads
WHERE location = subs.id
ORDER BY time_submitted DESC
LIMIT 1
)
LIMIT 1
) AS author,
(
SELECT COUNT(*)
FROM threads
WHERE location = subs.id
ORDER BY time_submitted DESC
LIMIT 1
) AS thread_count
FROM (
SELECT *
FROM categories
WHERE parent_id = #catlocation
) AS subs
When I try to run this through PHP I get a false result and an error of:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT subs.display_name AS display, subs.url_name AS url, ( SELECT threads.' at line 7
I have no idea what the syntax error could be, if someone could point it out to me that would be wonderful.
EDIT: Could this be caused by having two select statements (The one that sets #catlocation and the main query?)
You can refactor your request with joins to increase performance.
SELECT s.display_name display, s.url_name url,
t1.title, u.username author,
COUNT(t2.title) total
FROM categories s
LEFT JOIN threads t1 ON t1.id = (SELECT id FROM threads
WHERE location = s.id
ORDER BY time_submitted DESC
LIMIT 1)
LEFT JOIN users u ON u.uid = t1.uid
LEFT JOIN threads t2 ON t2.location = s.id
WHERE s.parent_id = #catlocation
GROUP BY s.display_name, s.url_name, t1.title, u.username
In a ansi SQL you need to declare a tag for each table or omit it if there is only one. Try taking out the "threads." everywhere, it is not needed
It appears the first SELECT statement which set #catlocation was causing the problem. I moved it into a subquery and the query executed successfully
The new query is as follows:
SELECT categories.display_name display,
categories.url_name url,
threads.title title,
users.username author,
( SELECT COUNT(title)
FROM threads
WHERE location = categories.id
) total
FROM categories
LEFT JOIN threads
ON threads.tid = ( SELECT tid
FROM `threads`
WHERE location = categories.id
ORDER BY time_submitted DESC
LIMIT 1 )
LEFT JOIN users ON users.uid = threads.uid
WHERE categories.parent_id = ( SELECT id
FROM `categories`
WHERE url_name='hexcode'
LIMIT 1 );
I will continue to refactor the query by using JOINs (once I learn how to use them). Thanks to all that suggested fixes, I didn't understand the JOIN answer and still couldn't get it to run without error.

`ORDER BY` before `GROUP BY` in a request with INNER JOIN?

Initially I need to build a query fetching sites from one table ordered by date of newest article (articles placed in the separate table).
I build the following query:
SELECT *
FROM `sites`
INNER JOIN `articles` ON `articles`.`site_id` = `sites`.`id`
ORDER BY `articles`.`date` DESC
GROUP BY `sites`.`id`
I supposed that SELECT and INNER JOIN will fetch all posts and associate a site to each one, than ORDER BY will order the result by descending of post date than GROUP BY will take the very first post for each site and I will get the needed result.
But I'm receiving MySQL error #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP BYsites.idLIMIT 0, 30' at line 7
If I place GROUP BY before ORDER BY statement the query is working but it will not give me the newest post for each site. Instead the result will be sorted after the grouping which is not the thing I need (actually I could prefer to order in another way after grouping).
I read several pretty similar questions but they all related to the data stored in a single table making it possible to use MAX and MIN functions.
What should I do to implement what I need?
You can use either a subquery / derived-table / inline-view or a self-exclusion join, e.g.:
SELECT s.*, a1.*
FROM `sites` s
INNER JOIN `articles` a1 ON a1.`site_id` = s.`id`
LEFT OUTER JOIN `articles` a2 ON a2.`site_id` = a1.`site_id`
AND a2.`date` > a1.`date`
WHERE
a2.`site_id` IS NULL
ORDER BY
a1.`date` DESC
The principle is that you select the sites for which there is no article date greater than any other article date.
rewrite the sql to the following syntax -
SELECT `articles`.`article_name`,'sites'.'id','articles'.'site_id'
FROM `sites`,'articles'
WHERE `articles`.`site_id` = `sites`.`id`
ORDER BY 'sites'.'id', `articles`.`date` DESC;
Do something like this in the select statement. Group by function demands that all fields to be grouped. Hence usage of * is not possible.
SELECT * FROM ( SELECT `S.<col1>`, `S.<col2>`, `A.<col1>`,`A.<col2>`,
ROW_NUMBER ()
OVER (PARTITION BY `SITES`.`ID`
ORDER BY `SITES`.`ID` DESC)
RID
FROM `SITES` `S`,`ARTICLES` `A`
WHERE `ARTICLES`.`SITE_ID` = `SITES`.`ID`
)
WHERE RID = 1;
Can you try this?
Finally I came to the solution.
First of all I changed the main query from queering from sites table to queering from articles. Next I added the MAX(date) column to the result.
So the resulting query implementing the thing I need is the following:
SELECT `sites`.`url`,MAX(`articles`.`date`) AS `last_article_date`
FROM `articles`
INNER JOIN `sites` ON `sites`.`id` = `article`.`site_id`
GROUP BY `site_id`
ORDER BY `last_article_date` ASC
Thanks to all of you for giving me hints and right search directions!

MySQL - Operand should contain 1 column(s)

While working on a system I'm creating, I attempted to use the following query in my project:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
WHERE topics.cat_id = :cat
GROUP BY topics.id
":cat" is bound by my PHP code as I'm using PDO. 2 is a valid value for ":cat".
That query though gives me an error: "#1241 - Operand should contain 1 column(s)"
What stumps me is that I would think that this query would work no problem. Selecting columns, then selecting two more from another table, and continuing on from there. I just can't figure out what the problem is.
Is there a simple fix to this, or another way to write my query?
Your subquery is selecting two columns, while you are using it to project one column (as part of the outer SELECT clause). You can only select one column from such a query in this context.
Consider joining to the users table instead; this will give you more flexibility when selecting what columns you want from users.
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
users.username AS posted_by,
users.id AS posted_by_id
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
LEFT OUTER JOIN users ON users.id = posts.posted_by
WHERE topics.cat_id = :cat
GROUP BY topics.id
In my case, the problem was that I sorrounded my columns selection with parenthesis by mistake:
SELECT (p.column1, p.column2, p.column3) FROM table1 p WHERE p.column1 = 1;
And has to be:
SELECT p.column1, p.column2, p.column3 FROM table1 p WHERE p.column1 = 1;
Sounds silly, but it was causing this error and it took some time to figure it out.
This error can also occur if you accidentally use commas instead of AND in the ON clause of a JOIN:
JOIN joined_table ON (joined_table.column = table.column, joined_table.column2 = table.column2)
^
should be AND, not a comma
This error can also occur if you accidentally use = instead of IN in the WHERE clause:
FOR EXAMPLE:
WHERE product_id = (1,2,3);
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Well, you can’t get multiple columns from one subquery like that. Luckily, the second column is already posts.posted_by! So:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
posts.posted_by
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by_username
FROM users
WHERE users.id = posts.posted_by)
...
I got this error while executing a MySQL script in an Intellij console, because of adding brackets in the wrong place:
WRONG:
SELECT user.id
FROM user
WHERE id IN (:ids); # Do not put brackets around list argument
RIGHT:
SELECT user.id
FROM user
WHERE id IN :ids; # No brackets is correct
This error can also occur if you accidentally miss if function name.
for example:
set v_filter_value = 100;
select
f_id,
f_sale_value
from
t_seller
where
f_id = 5
and (v_filter_value <> 0, f_sale_value = v_filter_value, true);
Got this problem when I missed putting if in the if function!
Another place this error can happen in is assigning a value that has a comma outside of a string. For example:
SET totalvalue = (IFNULL(i.subtotal,0) + IFNULL(i.tax,0),0)
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Here you using sub-query but this sub-query must return only one column.
Separate it otherwise it will shows error.
I also have the same issue in making a company database.
this is the code
SELECT FNAME,DNO FROM EMP
WHERE SALARY IN (SELECT MAX(SALARY), DNO
FROM EMP GROUP BY DNO);