MySQL Query Order by before Group By - mysql

name order_id
tom | 1 |
tom | 0 |
tom | 2 |
tom | 3 |
tom | 4 |
ken | 2 |
ken | 1 |
ken | 0 |
I have a table like above, how can I select the data group by the name and order by the order id. I already try the query below but it's not the result I want.
SELECT * FROM tbl_dummy GROUP BY name ORDER BY order_id ASC

This might be what you want:
SELECT name, MIN(order_id) AS order_id
FROM tbl_dummy
GROUP BY name
ORDER BY order_id

SELECT * FROM tbl_dummy GROUP by name,order_id order by name,order_id

For using GROUP BY clause, you must use some type of aggregate function (SUM, MIN, MAX ..) on all the other columns that you are selecting.
Try understand it this way, if you do group by name in the above data, then you will have two rows in the result, one for tom and one for ken. But what value of order_id should it display against each name? It cannot display all the values separated by comma (or anything else like that). The value to be shown must be a value calculated using all the values corresponding to that name. It could either be sum, average, min or max of all the values.
Ref: http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
May be what you are looking for is to order your results by name first and then order_id in increasing order. In that case you can use order by multiple columns
SELECT name, order_id from yourtable order by name, order_id;

Related

How to iterate over possible values over values of a column

I have a table, which stores names and numbers associated with it. Each of these numbers are of a certain type. The combination of name and type is unique.
name | type | number
---------------------
a | t0 | 5
a | t1 | 6
b | t0 | 7
c | t1 | 8
And I want this table as a result, which shows the numbers which are associated with that name, regardless of type accumulated.
name | sum
------------
a | 11
c | 8
b | 7
Now I know the SUM() function and I have written this so far:
SELECT name, SUM( ??SELECT name, SUM(number) WHERE name = 'a'?? ) AS sum
FROM table
ORDER BY sum DESC;
The thing is I don't know how to write the inner part of the SUM() function, as I can't use SELECT statements inside of functions. Also I don't know how I can iterate over the possible values of the name column.
SELECT NAME,
Sum(number) As 'Sum'
FROM table
GROUP BY NAME
ORDER BY Sum(number) DESC;
You need to use GROUP BY along with SUM:
SELECT name, SUM(number) AS sum
FROM tableName
GROUP BY name
ORDER BY SUM(number) DESC; -- or ORDER BY sum DESC; - it is identical

ORDER BY does not work if COUNT is used

I have a table with following content
loan_application
+----+---------+
| id | user_id |
+----+---------+
| 1 | 10 |
| 2 | 10 |
| 3 | 10 |
+----+---------+
I want to fetch 3rd record only if there are 3 records available, in this case i want id 3 and total count must be 3, here is what i expect
+--------------+----+
| COUNT(la.id) | id |
+--------------+----+
| 3 | 3 |
+--------------+----+
Here is the query i tried.
SELECT COUNT(la.id), la.id FROM loan_application la HAVING COUNT(la.id) = 3 ORDER BY la.id DESC;
However this gives me following result
+--------------+----+
| COUNT(la.id) | id |
+--------------+----+
| 3 | 1 |
+--------------+----+
The problem is that it returns id 1 even if i use order by id descending, whereas i am expecting the id to have value of 3, where am i going wrong ?
Thanks.
In your case u can use this query:
SELECT COUNT(la.id), max(la.id) FROM loan_application la
GROUP BY user_id
I try your table in my db MySQL
When you have a group by function (in this instance count()) in the select list without a group by clause, then mysql will return a single record only with the function applied to the whole table.
Mysql under certain configuration settings allow you to include fields in the select loist which are not in the group by clause, nor are aggregated. Mysql pretty much picks up the 1st value it encounters while scanning the data as a value for such fields, in your case the value 1 for id.
If you want to fetch the record where id=count of records within the table, then I would use the following query:
select *
from loan_application
join (select count(*) as numrows from loan_application) t
where id=t.numrows and t.numrows=3
However, this implies that the values within the id field are continuous and there are no gaps.
You are selecting la.id along with an aggregated function (COUNT). So after iterating the first record the la.id is selected but the count goes on. So in this case you will get the first la.id not the last. In order to get the last la.id you need to use the max function on that field.
Here's the updated query:
SELECT
COUNT(la.id),
MAX(la.id)
FROM
loan_application la
GROUP BY user_id
HAVING
COUNT(la.id) = 3
N:B: You are using COUNT without a GROUP BY Function. So this particular aggregated function is applied to the whole table.

how to find duplicate count without counting original

I need to count the number of duplicate emails in a mysql database, but without counting the first one (considered the original). In this table, the query result should be the single value "3" (2 duplicate x#q.com plus 1 duplicate f#q.com).
TABLE
ID | Name | Email
1 | Mike | x#q.com
2 | Peter | p#q.com
3 | Mike | x#q.com
4 | Mike | x#q.com
5 | Frank | f#q.com
6 | Jim | f#q.com
My current query produces not one number, but multiple rows, one per email address regardless of how many duplicates of this email are in the table:
SELECT value, count(lds1.leadid) FROM leads_form_element lds1 LEFT JOIN leads lds2 ON lds1.leadID = lds2.leadID
WHERE lds2.typesID = "31" AND lds1.formElementID = '97'
GROUP BY lds1.value HAVING ( COUNT(lds1.value) > 1 )
It's not one query so I'm not sure if it would work in your case, but you could do one query to select the total number of rows, a second query to select distinct email addresses, and subtract the two. This would give you the total number of duplicates...
select count(*) from someTable;
select count(distinct Email) from someTable;
In fact, I don't know if this will work, but you could try doing it all in one query:
select (count(*)-(count(distinct Email))) from someTable
Like I said, untested, but let me know if it works for you.
Try doing a group by in a sub query and then summing up. Something like:
select sum(tot)
from
(
select email, count(1)-1 as tot
from table
group by email
having count(1) > 1
)

Select Distinct value SQL

I have table like this
-------------------------------------------------------------------
id | title | image | name |
-------------------------------------------------------------------
1 | xyzab | so.jpg | googl |
2 | acbde | am.jpg | artic |
3 | xyzab | pp.jpg | other |
i want to select unique or distinct title with it's image and name also.
DO not want to repeat the values. I use this this code
SELECT DISTINCT title,image,name,id FROM `some_table`
but this is not working fine
NOTE: The OP is working with MySQL
Using DISTINCT will ensure no 2 records have all columns matching, so this is working correctly.
If you want to return unique titles, you need to decide what image and name would be returned.
You could use a group by with an aggregate function to do this. For example:
SELECT title, MIN(image), MIN(name), MIN(id)
FROM `some_table`
GROUP BY title
But it depends on what results you are after...
You will need to specify the WINNER... in other words if there is a duplicate title but differening data in other columns you need to pick one...
For example you could try this.
select * from 'some_table' where id in (select min(id) from 'some_table' group by title)
DISTINCT is not applied to the one field after the keyword, but for fields in your select statement. What you're looking for is GROUP BY:
SELECT title,image,name,id FROM some_table GROUP BY title

MySQL - Exclude rows from Select based on duplication of two columns

I am attempting to narrow results of an existing complex query based on conditional matches on multiple columns within the returned data set. I'll attempt to simplify the data as much as possible here.
Assume that the following table structure represents the data that my existing complex query has already selected (here ordered by date):
+----+-----------+------+------------+
| id | remote_id | type | date |
+----+-----------+------+------------+
| 1 | 1 | A | 2011-01-01 |
| 3 | 1 | A | 2011-01-07 |
| 5 | 1 | B | 2011-01-07 |
| 4 | 1 | A | 2011-05-01 |
+----+-----------+------+------------+
I need to select from that data set based on the following criteria:
If the pairing of remote_id and type is unique to the set, return the row always
If the pairing of remote_id and type is not unique to the set, take the following action:
Of the sets of rows for which the pairing of remote_id and type are not unique, return only the single row for which date is greatest and still less than or equal to now.
So, if today is 2011-01-10, I'd like the data set returned to be:
+----+-----------+------+------------+
| id | remote_id | type | date |
+----+-----------+------+------------+
| 3 | 1 | A | 2011-01-07 |
| 5 | 1 | B | 2011-01-07 |
+----+-----------+------+------------+
For some reason I'm having no luck wrapping my head around this one. I suspect the answer lies in good application of group by, but I just can't grasp it. Any help is greatly appreciated!
/* Rows with exactly one date - always return regardless of when date occurs */
SELECT id, remote_id, type, date
FROM YourTable
GROUP BY remote_id, type
HAVING COUNT(*) = 1
UNION
/* Rows with more than one date - Return Max date <= NOW */
SELECT yt.id, yt.remote_id, yt.type, yt.date
FROM YourTable yt
INNER JOIN (SELECT remote_id, type, max(date) as maxdate
FROM YourTable
WHERE date <= DATE(NOW())
GROUP BY remote_id, type
HAVING COUNT(*) > 1) sq
ON yt.remote_id = sq.remote_id
AND yt.type = sq.type
AND yt.date = sq.maxdate
The group by clause groups all rows that have identical values of one or more columns together and returns one row in the result set for them. If you use aggregate functions (min, max, sum, avg etc.) that will be applied for each "group".
SELECT id, remote_id, type, max(date)
FROM blah
GROUP BY remote_id, date;
I'm not whore where today's date comes in, but assumed that was part of the complex query that you didn't describe and I assume isn't directly relevant to your question here.
Try this:
SELECT a.*
FROM table a INNER JOIN
(
select remote_id, type, MAX(date) date, COUNT(1) cnt from table
group by remote_id, type
) b
WHERE a.remote_id = b.remote_id,
AND a.type = b.type
AND a.date = b.date
AND ( (b.cnt = 1) OR (b.cnt>1 AND b.date <= DATE(NOW())))
Try this
select id, remote_id, type, MAX(date) from table
group by remote_id, type
Hey Carson! You could try using the "distinct" keyword on those two fields, and in a union you can use Count() along with group by and some operators to pull non-unique (greatest and less-than today) records!