Is there a simple way to retrieve a list of all unique values in a column, along with how many times that value appeared?
Example dataset:
A
A
A
B
B
C
... Would return:
A | 3
B | 2
C | 1
Use GROUP BY:
select value, count(*) from table group by value
Use HAVING to further reduce the results, e.g. only values that occur more than 3 times:
select value, count(*) from table group by value having count(*) > 3
SELECT id,COUNT(*) FROM file GROUP BY id
Related
I have two columns account_number and customer_id. A single customer can have multiple account but a single account can't have multiple customer.
I have dumped a file containing account_num and its corresponding customer_id to db through LOAD DATA INFILE command. Now I am trying to validate through query does any account which has come multiple times in a file has same customer_id or different customer_id in two different rows.
REQUIREMENT : i want to return those accounts which has come multiple times but having diferent customer ids
I tried with group by , but didn't get desired result.
This is my query which is not giving the desired result
SELECT ACCOUNT_NUM,UNIQUE_CUSTOMER_ID,COUNT(UNIQUE_CUSTOMER_ID)
FROM LINKAGE_FILE
GROUP BY ACCOUNT_NUM, UNIQUE_CUSTOMER_ID
HAVING COUNT(ACCOUNT_NUM) > 1 AND COUNT(UNIQUE_CUSTOMER_ID) = 1;
Hope I am clear.
You can simply get the count of unique customer ids using COUNT(DISTINCT..) for every account_num and filter out those cases where count is more than 1, inside the HAVING clause:
SELECT
ACCOUNT_NUM,
COUNT(DISTINCT CUSTOMER_ID) AS unique_customer_count
FROM LINKAGE_FILE
GROUP BY ACCOUNT_NUM
HAVING unique_customer_count > 1
Drop the customer check into a join query like so
DROP TABLE if exists t;
create table t(accountid int,cid int);
insert into t values
(1,1),(1,2).(1,1),(2,3),(3,4),(3,4);
select distinct t.accountid,t.cid
from t
join
(
select accountid,count(distinct cid) cids
from t
group by accountid having cids > 1
) s on s.accountid = t.accountid;
+-----------+------+
| accountid | cid |
+-----------+------+
| 1 | 1 |
| 1 | 2 |
+-----------+------+
2 rows in set (0.00 sec)
You can use EXISTS :
SELECT lf.*
FROM LINKAGE_FILE lf
WHERE EXISTS (SELECT 1 FROM LINKAGE_FILE lf1 WHERE lf1.ACCOUNT_NUM = lf.ACCOUNT_NUM AND lf1.UNIQUE_CUSTOMER_ID <> lf.UNIQUE_CUSTOMER_ID);
However, you can also aggregation with your query :
SELECT ACCOUNT_NUM, COUNT(DISTINCT UNIQUE_CUSTOMER_ID)
FROM LINKAGE_FILE
GROUP BY ACCOUNT_NUM
HAVING COUNT(DISTINCT UNIQUE_CUSTOMER_ID) > 1;
By this, you can get only ACCOUNT_NUMs which have two or more CUSTOMER_IDs.
I want to select a data in where clause. Say that I have $values: 1,2,3,4
And then I want to select rows from table in that values.
SELECT `date` from another_table where id in (1,2,3,4)
If another_table only have rows with id 1,2 and 3 only, it mean that the id of 4 is not exist. I want the id of 4 is still selected with return of null or nol or NEVER.
another_table
-------+-------------+
| id | date |
----------------------
1 Yesterday
2 Today
3 Tomorow
5 Today
The expected result would be
-------+-------------+
| id | date |
----------------------
1 Yesterday
2 Today
3 Tomorow
4 Never
How to do this?
Thanks in advance
As one option use an inline view as a rowsource, and perform an outer join operation. We can use an IF expression to check whether a matching row was returned from another_table, we know the id value will not be NULL if there was a matching row, the join predicate (in the ON clause) guarantees us that.)
As an example:
SELECT n.id
, IF(a.id IS NULL,'Never',a.date) AS `date`
FROM ( SELECT 1 AS id
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
) n
LEFT
JOIN another_table a
ON a.id = n.id
ORDER BY n.id
The inline view query gets executed, and the results are materialized into a temporary table (MySQL calls it a derived table). When the outer query runs, n is effectively a table containing 4 rows.
Obviously, if the list of id values has to change, you'd need to change the view definition. The SQL text for the inline view can be generated dynamically from an array in a programming language from an array.
For a large number of values, the inline view becomes unwieldy, and you'd get better performance from a table, rather than the view.
I have a MySQL table like this
id Name count
1 ABC 1
2 CDF 3
3 FGH 4
using simply select query I get the values as
1 ABC 1
2 CDF 3
3 FGH 4
How I can get the result like this
1 ABC 1
2 CDF 3
3 FGH 4
4 NULL 0
You can see Last row. When Records are finished an extra row in this format
last_id+1, Null ,0 should be added. You can see above. Even I have no such row in my original table. There may be N rows not fixed 3,4
The answer is very simple
select (select max(id) from mytable)+1 as id, NULL as Name, 0 as count union all select id,Name,count from mytable;
This looks a little messy but it should work.
SELECT a.id, b.name, coalesce(b.`count`) as `count`
FROM
(
SELECT 1 as ID
UNION
SELECT 2 as ID
UNION
SELECT 3 as ID
UNION
SELECT 4 as ID
) a LEFT JOIN table1 b
ON a.id = b.id
WHERE a.ID IN (1,2,3,4)
UPDATE 1
You could simply generate a table that have 1 column preferably with name (ID) that has records maybe up 10,000 or more. Then you could simply join it with your table that has the original record. For Example, assuming that you have a table named DummyRecord with 1 column and has 10,000 rows on it
SELECT a.id, b.name, coalesce(b.`count`) as `count`
FROM DummyRecord a LEFT JOIN table1 b
ON a.id = b.id
WHERE a.ID >= 1 AND
a.ID <= 4
that's it. Or if you want to have from 10 to 100, then you could use this condition
...
WHERE a.ID >= 10 AND
a.ID <= 100
To clarify this is how one can append an extra row to the result set
select * from table union select 123 as id,'abc' as name
results
id | name
------------
*** | ***
*** | ***
123 | abc
Simply use mysql ROLLUP.
SELECT * FROM your_table
GROUP BY Name WITH ROLLUP;
select
x.id,
t.name,
ifnull(t.count, 0) as count
from
(SELECT 1 AS id
-- Part of the query below, you will need to generate dynamically,
-- just as you would otherwise need to generate 'in (1,2,3,4)'
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
) x
LEFT JOIN YourTable t
ON t.id = x.id
If the id does not exist in the table you're selecting from, you'll need to LEFT JOIN against a list of every id you want returned - this way, it will return the null values for ones that don't exist and the true values for those that do.
I would suggest creating a numbers table that is a single-columned table filled with numbers:
CREATE TABLE `numbers` (
id int(11) unsigned NOT NULL
);
And then inserting a large amount of numbers, starting at 1 and going up to what you think the highest id you'll ever see plus a thousand or so. Maybe go from 1 to 1000000 to be on the safe side. Regardless, you just need to make sure it's more-than-high enough to cover any possible id you'll run into.
After that, your query can look like:
SELECT n.id, a.*
FROM
`numbers` n
LEFT JOIN table t
ON t.id = n.id
WHERE n.id IN (1,2,3,4);
This solution will allow for a dynamically growing list of ids without the need for a sub-query with a list of unions; though, the other solutions provided will equally work for a small known list too (and could also be dynamically generated).
When I use this:
SELECT DISTINCT id FROM table
this works! but... when I want to filter only one column I try to do this:
SELECT DISTINCT prod_id, id, prod_picture FROM products
this gives me all table... I just need 1 picture for each product, like:
1 | 1 | asd.jpg
2 | 3 | weq.jph
not
1 | 1 | asd.jpg
1 | 2 | qwe.jpg
2 | 3 | weq.jpg
actually I try to use this:
SELECT DISTINCT
prod_list.id,
prod_list.prodname,
prod_pict.pict_file
FROM
prod_list
INNER JOIN urun_pict ON (prod_list.id = prod_pict_prod_id)
I have to filter just "prod_list.id"...
You should GROUP BY the product id to collapse all rows for each id into one. All columns which are not part of your GROUP BY clause should be aggregate columns. You need to tell MySQL which of the possibly multiple values for the other columns you want. If you don't care, use MIN or MAX?
SELECT
prod_list.id,
prod_list.prodname,
MAX(prod_pict.pict_file) AS `pict_file`,
FROM
prod_list
INNER JOIN
prod_pict
ON
prod_list.id = prod_pict.prod_id
GROUP BY
prod_list.id,
prod_list.prodname
SELECT prod_id, id, prod_picture
FROM products
GROUP BY prod_id
use group by prod_id,
SELECT prod_id, id, prod_picture FROM products group by prod_id
work only if in run not with this sql_mode : ONLY_FULL_GROUP_BY , The default value is empty (no modes set).
SELECT
prod_list.id,
prod_list.prodname,
prod_pict.pict_file
FROM
prod_list
INNER JOIN urun_pict ON (prod_list.id = prod_pict_prod_id)
GROUP BY prod_list.id
This should work.
I have database result like this
ID | NAME | TYPE
--------------------
1 | baseball | 1
2 | kickball | 1
3 | football | 1
4 | soccer | 2
How do I do a select * so get all results but also get a total count of type = 2 in the results?
Any help appreciated.
This will give you the type count for the current row's type in each row:
select t1.*, t2.TypeCount
from Table1 t1
inner join (
select TYPE, count(*) as TypeCount
from Table1
group by TYPE
) t2 on t1.TYPE = t2.TYPE
Typically we manage to get this by the way of two distinct results set. However it is possible to get them all in one with a query similar to the following
SELECT ID, Name, Type
FROM MyTable
UNION
SELECT -1, Type, COUNT(*)
FROM MyTable
WHERE Type = 2
GROUP BY Type
ORDER BY ID
The assumption is that all normal IDs are > 0 allowing to the the -1 as a marker for the row with the count. This row will be first in the resultset, thanks to the ORDER BY.
Note that we could complicate things a bit and get a count for all types (or for several), by simply removing (or changing) the WHERE clause in the second query.