count value for each unique id - mysql

I have a table
id value
1 a
2 a
3 b
4 b
5 b
6 c
My id is primary.
I have total 2 a , 3 b and 1 c. So I want to count total repeat value in each primary id which matches on it
I want this format
id value_count
1 2
2 2
3 3
4 3
5 3
6 1

Try this query:
SELECT a.id, b.valueCnt
FROM tableA a
INNER JOIN (SELECT a.value, COUNT(a.value) valueCnt
FROM tableA a GROUP BY a.value) AS B ON a.value = b.value;
Check the SQL FIDDLE DEMO
OUTPUT
| ID | VALUECNT |
|----|----------|
| 1 | 2 |
| 2 | 2 |
| 3 | 3 |
| 4 | 3 |
| 5 | 3 |
| 6 | 1 |

Try This
select id, value_count from tablename as a1
join (select count(*) as value_count, value from tablename group by value) as a2
on a1.value= a2.value

I suggest you use a subselect without any joins:
SELECT
a.id,(SELECT COUNT(*) FROM tableA WHERE value = a.value) as valueCnt
FROM tableA a
Fiddle Demo

You need to use subquery.
SELECT table.id , x.value_count
FROM table
INNER JOIN
(SELECT t1.value, count(t1.id) as value_count
FROM table t1
Group by t1.value
) x on x.value = table.value

Related

How to select the ids present in another table multiple columns?

Suppose I have two tables TableA and TableB having structure as shown below:-
**TableA**
id | col_1 | col_2
1 | A | B
2 | C | D
3 | E | F
4 | G | H
**TableB**
id | TableA_first_col_id | TableA_second_col_id
1 | 1 | 2
2 | 1 | 3
Now, I want to check if TableA id is present in TableB TableA_first_col_id column or in TableA_second_col_id column.
Result should come to be
**TableA.id**
1
2
3
How can I write an optimised mysql query for this?
Try below ;
Select A.id
From TableA A
Where A.id in (select TableA_first_col_id From TableB) OR
A.id in (select TableA_second_col_id from TableB)
select *
from table1 t1
where not exists (
select 1
from table2 t2
where t1.id = t2.id and t1.program = t2.program
)
select id from tableA where exists
( select id
from tableB
where tableA.id = tableB.first_col_id or tableA.id = tableB.second_col_id
)

SQL: Get an article for each category

There are two tables article and category.
nid | title | status
---+-------------+-------
1 | abc | 1
2 | ggg | 1
3 | kkk | 0
4 | rrr | 1
5 | fff | 1
6 | ggg | 1
Where status = 1 is published.
cid | nid
---+-------------
1 | 1
2 | 2
2 | 3
3 | 4
1 | 5
2 | 6
Now I want to get a one nid for each cid, no double occurrence of cid where status is 1.
You can use GROUP BY with JOIN, e.g.:
SELECT t2.cid, MAX(t2.nid)
FROM table2 t2 JOIN table1 t1 ON t2.nid = t1.nid and t1.status = 1
GROUP BY t2.cid;
First of all you must decide which nid to show for a cid in case of multiple matches. Let's say you want the maximum nid. Select from category and look up articles for their status. Then aggregate.
select cid, max(nid)
from category
where nid in (select nid from article where status = 1)
group by cid;
You can use aggregation:
select c.cid, max(c.nid)
from category c join
article a
on c.nid = a.nid
where a.status = 1
group by c.cid;
Try this one.
SELECT DISTINCT cid
FROM category AS a1
INNER JOIN article AS a2 ON a1.nid = a2.nid
WHERE a1.[STATUS] = 1

Get min price id without inner select

I have a table called a with this data:
+-----+-----------+-------+
| id | parent_id | price |
+-----+-----------+-------+
| 1 | 1 | 100 |
| 2 | 1 | 200 |
| 3 | 1 | 99 |
| 4 | 2 | 1000 |
| 5 | 2 | 999 |
+-----+-----------+-------+
I want to get the id of min pirce for each parent_id.
There is any way to get this result without subquery?
+-----+-----------+-------+
| id | parent_id | price |
+-----+-----------+-------+
| 3 | 1 | 99 |
| 5 | 2 | 999 |
+-----+-----------+-------+
SELECT D1.id, D1.parent_id, D1.price
FROM Data D1
LEFT JOIN Data D2 on D2.price < D1.price AND D1.parent_id = D2.parent_id
WHERE D2.id IS NULL
Here is a shot at how to do it without subqueries. I haven't tested, let me know if it works!
SELECT t.id, t.parent_id, t.price
FROM table t
LEFT JOIN table t2
ON (t.parent_id = t2.parent_id AND t.price > t2.price)
GROUP BY t.id, t.parent_id, t.price
HAVING COUNT(*) = 1 AND max(t2.price) is null
ORDER BY t.parent_id, t.price desc;
Try this:
SELECT T1.id,T2.parent_id,T2.price FROM
(SELECT id,price
FROM TableName) T1
INNER JOIN
(
SELECT parent_id,MIN(price) as price
FROM TableName
GROUP BY parent_id) T2 ON T1.price=T2.price
See result in SQL Fiddle.
Try group by,
SELECT parent_id,min(price)
FROM TableName
GROUP BY parent_id
You can do this with a LEFT JOIN
SELECT a.id, a.parent_id, a.price
FROM a
LEFT JOIN a AS b ON b.price < a.price AND b.parent_id = a.parent_id
WHERE b.id IS NULL
Find the results at this fiddle:
http://sqlfiddle.com/#!2/09c888/10
You can try this without using any join or subquery you will surely get the desired result.
SELECT TOP 2 FROM a ORDER BY price

Mysql order by subquery id : where a.id = b.id, orders by b.id , query shouldnt order, but it does

My goal is to order results by distance.
I could use FIELD() to order by, but with 1000's of city's it does not really seem efficient, and the query grows very large, besides i have to build the query with php and run multipe queries.
In stead of putting the "complex" query here i simplified it.
select a.id from
(select 1 as id union select 2 as id union select 3 as id) a,
(select 2 as id union select 3 as id union select 1 as id) b
where a.id = b.id ;
Result
+----+
| id |
+----+
| 2 |
| 3 |
| 1 |
+----+
My questions are:
1) Why does this query order by b.id? That is actually what i want, but i dont get why it does so.
2) Could this query be written more efficient?
What i have tried so far which does not work:
select a.id from
(select 1 as id union select 2 as id union select 3 as id) a,
(select 2 as id union select 3 as id union select 1 as id) b
order by a.id = b.id desc;
Does not work. Results:
+----+
| id |
+----+
| 1 |
| 3 |
| 1 |
| 2 |
| 2 |
| 3 |
+----+
[EDIT removed production query]
[EDIT 2 more examples, that i seems like it is ordering by select order of b.id]
select a.id from
(select 1 as id union select 2 as id union select 3 as id) a,
(select 1 as id union select 2 as id union select 3 as id) b
where a.id = b.id;
Result
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
select a.id from
(select 1 as id union select 2 as id union select 3 as id) a,
(select 3 as id union select 2 as id union select 1 as id) b
where a.id = b.id;
Result
+----+
| id |
+----+
| 3 |
| 2 |
| 1 |
+----+
[EDIT 4, same ordering behaviour when used: order by a.id IN (b.id) ]
select a.id from
(select 1 as id union select 2 as id union select 3 as id) a,
(select 1 as id union select 2 as id union select 3 as id) b
where a.id IN ( b.id );
Result
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
select a.id from
(select 1 as id union select 2 as id union select 3 as id) a,
(select 3 as id union select 1 as id union select 2 as id) b
where a.id IN ( b.id );
Result
+----+
| id |
+----+
| 3 |
| 1 |
| 2 |
+----+
The answer to your first question is simple. SQL result sets are unordered unless you use order by. (Or, in MySQL rely on the deprecated ordering done by group by.) The SQL engine can process the data however it likes. And produce the results however it likes. The resulting order is arbitrary.
Your first query cannot be written more "efficiently", but proper join syntax is highly recommended:
select a.id
from (select 1 as id union select 2 as id union select 3 as id
) a join
(select 2 as id union select 3 as id union select 1 as id
) b
on a.id = b.id;
The second is more interesting. Let's look at it:
select a.id
from (select 1 as id union select 2 as id union select 3 as id) a,
(select 2 as id union select 3 as id union select 1 as id) b
order by a.id = b.id desc;
You are doing a cross join between two lists of numbers -- using (horror of horrors) implicit join syntax instead of cross join.
Your order by now has the condition a.id = b.id desc. Well, in MySQL, a.id = b.id becomes a boolean, which takes on a value of 1 for true and 0 for false. So, this will order the Cartesian product, putting the matches at the top of the list. It does no filtering

Mysql - Select at least one or select none

I have a table as so...
----------------------------------------
| id | name | group | number |
----------------------------------------
| 1 | joey | 1 | 2 |
| 2 | keidy | 1 | 3 |
| 3 | james | 2 | 2 |
| 4 | steven | 2 | 5 |
| 5 | jason | 3 | 2 |
| 6 | shane | 3 | 3 |
----------------------------------------
I'm running a select like so:
SELECT * FROM table WHERE number IN (2,3);
The problem im trying to solve is that I want to only grab get results from groups that have 1 or more rows of each number. For instance the above query is returning id's 1-2-3-5-6, when I'd like the results to exclude id 3 since the group of '2' can only return 1 result for the number of '2' and not for BOTH 2 and 3, since there's no row with the number 3 for the group 2 i'd like it to not even select id 3 at all.
Any help would be great.
Try it this way
SELECT *
FROM table1 t
WHERE number IN(2, 3)
AND EXISTS
(
SELECT *
FROM table1
WHERE number IN(2, 3)
AND `group` = t.`group`
GROUP BY `group`
HAVING MAX(number = 2) > 0
AND MAX(number = 3) > 0
)
or
SELECT *
FROM table1 t JOIN
(
SELECT `group`
FROM table1
WHERE number IN(2, 3)
GROUP BY `group`
HAVING MAX(number = 2) > 0
AND MAX(number = 3) > 0
) q
ON t.`group` = q.`group`;
or
SELECT *
FROM table1
WHERE `group` IN
(
SELECT `group`
FROM table1
WHERE number IN(2, 3)
GROUP BY `group`
HAVING MAX(number = 2) > 0
AND MAX(number = 3) > 0
);
Sample output (for both queries):
| ID | NAME | GROUP | NUMBER |
|----|-------|-------|--------|
| 1 | joey | 1 | 2 |
| 2 | keidy | 1 | 3 |
| 5 | jason | 3 | 2 |
| 6 | shane | 3 | 3 |
Here is SQLFiddle demo
On this, you can approach from a fun way with multiple joins for what you WANT qualified, OR, apply a prequery to get all qualified groups as others have suggested, but readability is a bit off for me..
Anyhow, here's an approach going through the table once, but with joins
select DISTINCT
T.id,
T.Name,
T.Group,
T.Number
from
YourTable T
Join YourTable T2
on T.Group = T2.Group AND T2.Group = 2
Join YourTable T3
on T.Group = T3.Group AND T3.Group = 3
where
T.Number IN ( 2, 3 )
So on the first record, it is pointing to by it's own group to the T2 group AND the T2 group is specifically a 2... Then again, but testing the group for the T3 instance and T3's group is a 3.
If it cant complete the join to either of the T2 or T3 instances, the record is done for consideration, and since indexes work great for joins like this, make sure you have one index for your NUMBER criteria, and another index on the (GROUP, NUMBER) for those comparisons and the next query sample...
If doing by more than this simple 2, but larger group, prequery qualified groups, then join to that
select
YT2.*
from
( select YT1.group
from YourTable YT1
where YT1.Number in (2, 3)
group by YT1.group
having count( DISTINCT YT1.group ) = 2 ) PreQualified
JOIN YourTable YT2
on PreQualified.group = YT2.group
AND YT2.Number in (2,3)
Maybe this,if I understand you
SELECT id FROM table WHERE `group` IN
(SELECT `group` FROM table WHERE number IN (2,3)
GROUP BY `group`
HAVING COUNT(DISTINCT number)=2)
SQL Fiddle
This will return all ids where BOTH numbers exist in a group.Remove DISTINCT if you want ids for groups where just one numbers is in.