MySQL - select rows where count in joined table equals 1 - mysql

I need to select the rows from table "web_users" only if rows of another joined table called "web_users_branches" equals to 1.
What I have now:
SELECT id, code from web_users
JOIN
(
SELECT client_code
FROM web_users_branches
HAVING COUNT(*) = 1
) as t2
ON web_users.code = t2.client_code;
I get empty result.
Database example:
Web Users table:
id code
1 0001
2 0002
3 0003
Web Users Branches table:
id client_code
1 0001
2 0001
3 0002
4 0003
5 0003
Now after this query I should get only the user which client_code is 0002, because all the other user client_code count is not equal to 1 (there is x2 0003 and x2 0001). Any ideas?

I think you just want a group by in the subquery:
SELECT u.id, u.code
FROM web_users u JOIN
(SELECT client_code
FROM web_users_branches
GROUP BY client_code
HAVING COUNT(*) = 1
) c
ON u.code = c.client_code;

SELECT id, code
FROM web_users_branches as t1
JOIN web_users as t2
ON t2.code = t1.client_code
HAVING COUNT(*) = 1
should work. After an inner join, you only get a single row when both(!) tables have exactly one record in the beginning.

Related

Check if ID from a table exists in another table, and if so, how many times

Let's say I have two tables
Table a
some_ID
1
2
3
4
Table b
some_ID
1
2
1
4
Now what I would like to receive is a table like
id amount
1 | 2
2 | 1
I tried with a following query:
SELECT COUNT(a.some_id) as id
FROM Table_a
INNER JOIN Table_b
ON Table_a.some_id = Table.b.some_id
but that only returned how many id rows there are in both tables.
Any help?
Do the grouping on table_b and then join that result set on table_a
SELECT b.* FROM
(
SELECT id, COUNT(*) AS Cnt
FROM Table_b
GROUP BY id
) b
INNER JOIN Table_a a ON a.id = b.id
SQLFiddle
If you want the zero counts:
SELECT a.some_id AS id, count(b.some_id) as amount
FROM a LEFT JOIN b ON a.some_id = b.some_id
GROUP BY a.some_id
Result:
id | amount
1 | 2
2 | 1
3 | 0
4 | 1
If not:
SELECT a.some_id AS id, count(*) as amount
FROM a INNER JOIN b ON a.some_id = b.some_id
GROUP BY a.some_id
Result:
id | amount
1 | 2
2 | 1
4 | 1
The difference is the join type. Once left outer join. Then inner join. Note that in the first case it is important to count with count(b.some_id). With count(*) the rows with missing b entries would be counted as 1. count(*) counts the rows. count(expression) counts the non-null values.
If I understand correctly, you want a histogram of histograms:
select cnt, count(*) as num_ids
from (select id, count(*) as cnt
from b
group by id
) b
group by cnt;

SQL Query - Find Duplicates with a Different Key

I have the following data:
id userid name group
1 1 A x
2 1 A y
3 1 A z
4 2 B x
5 2 B y
6 3 C y
7 4 D x
8 5 E x
9 5 E z
10 6 F x
I want to find those records that meet all this condition:
Select all rows where the a userid belongs to a group other than y but the userid also belongs to group y.
The resulting dataset will be as follows:
id userid name group
1 1 A x
3 1 A z
4 2 B x
If you see, it has resulted in two records for userid a because these are two two records belong to groups other than y but the userid 1 also belongs to group y. Same for userid 2.
I have been breaking my head on how to get this in an SQL statement but not even close to a solution.
Any help is appreciated.
Use a join:
SELECT t1.*
FROM mytable t1
INNER JOIN mytable t2
ON t1.user_id = t2.user_id AND t1.group <> t2.group AND t2.group = 'y'
I think that would be the fastest query (but please feel free to try the other solutions as well).
Add an index on user_id if not already there and maybe play with some other indexes as well (maybe a composite index on group and user_id can be utilized)
Use exists
select *
from MyTable a2
where name_group <> 'y'
and exists (select 1
from MyTable a2
where a2.name_group = 'y'
and a2.userid = a1.userid)
You can get all the users that meet the condition using aggregation and having:
select userid
from t
group by userid
having sum( group = 'y' ) > 0 and
sum( group <> 'y') > 0;
I leave it to your to put this into a query to get all the original rows.

MySQL - remove non-duplicate rows from query

I'm running a query that selects details of orders, and I want to see only the orders that have gone through multiple stages. My data looks like:
id | order_id | action
1 100 1
2 100 2
3 100 4
4 101 1
5 102 2
6 103 1
7 103 2
So that only the rows for order_id 100 and 103 will be selected. This needs to be nested in a larger query.
You can use a subquery to get the orders that had multiple stages:
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
then you can join this result back to your table:
SELECT o.*
FROM yourtable AS o INNER JOIN (
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
) dup ON o.order_id = dup.order_id
Use group by with count and having
select *,count(order_id) as total from table
group by order_id
having total > 1
you can try this query:
select * from your_table
where ( select count(*) from your_table internal_table
where your_table .order_id = internal_table.order_id
) > 1

I want to have Sum of individual columns of two different table and show it in a single query result where customer id matches?

Create or replace view cnPointsDetailsvw
as select sum(cd.value), sum(cd1.points)
from customerdetails cd left join
customerdetails1 cd1 on cd.customerid = cd1.customerid;
The problem is that the above query is calculating sum multiple times for the column cd1.points
If table customerdetails1 has only 1 row, so why you use SUM() function?
Just use MAX().
I am confused of your table, so let me give a sample structurs and data.
table1
id points
-----------
1 10
2 20
3 40
table2
id points
-----------
1 10
1 2
1 4
2 20
3 40
3 5
And your query should be looks like this :
CREATE OR REPLACE VIEW view_name AS
SELECT t1.id,max(t1.points) as points1, sum(t2.points) as points2
FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
GROUP BY t1.id
Your view should be looks like this :
id points1 points2
---------------------
1 10 16
2 20 20
3 30 45
Do the calculation in subqueries, then join their results:
SELECT
CD.sum_value, CD1.sum_points
FROM
(SELECT sum(value) as sum_value FROM customerdetails) CD
INNER JOIN (SELECT sum(points) AS sum_points FROM customerdetails1) CD1
ON 1 = 1
Please note, that SUM() returns NULL if there were no matching rows, so the subqueries will return with exactly one record -> any ON condition will be fine which results to true.
If you want to group by customers, then do the grouping in the subqueries:
SELECT
CD.customerid, CD.sum_value, CD1.sum_points
FROM
(
SELECT customerid, sum(value) as sum_value
FROM customerdetails
GROUP BY customerid
) CD
LEFT JOIN
(
SELECT customerid, sum(points) AS sum_points
FROM customerdetails1
GROUP BY customerid
) CD1
ON CD.customerid = CD1.customerid
UPDATE
To create a view (and bypass the limitation of MySQL), you have to create 3 views: 2 for the 2 subresults, 1 to join their results:
CREATE VIEW customer_value AS
SELECT SUM(value) as sum_value FROM customerdetails;
CREATE VIEW customer_points AS
SELECT SUM(points) as sum_points FROM customerdetails1;
CREATE VIEW cnPointsDetailsvw AS
SELECT cv.sum_value, cp.sum_points
FROM customer_value cv
INNER JOIN customer_points cp
ON 1=1;

My SQL query to retrieve 4 columns based on unique records from two columns

Hi I'm trying to write a correct query for MySQL to retrieve values from 4 columns (from, to, content, date or all if that's easier) based on 2 columns being unique in the same table. The idea is to retrieve a list of only last messages sent and received by a user X
TABLE
msg_id|msg_from|msg_to|msg_new|msg_content|date
1 user1 sw1 1 message1 2014-02-06
2 user1 sw1 1 message2 2014-02-06
3 user1 sw3 0 message3 2014-02-06
4 user1 sw5 0 message4 2014-02-06
5 sw2 sm2 1 message5 0000-00-00
6 sw2 sm4 1 message6 2014-02-20
7 sw1 user1 1 message7 2014-02-20
8 user1 sw5 1 message8 2014-02-20
My last attempt :
SELECT t1.* FROM (SELECT MAX(msg_id) AS nr, msg_from, msg_to
FROM com_msg GROUP BY msg_from) AS t2
INNER JOIN com_msg t1 ON t1.msg_from=t2.msg_from AND t1.msg_id=t2.nr
WHERE t1.msg_to='sw1' OR t1.msg_from='sw1'
which returns :
2| user1|sw1 |1|message2|2014-02-06
7| sw1 |user1|1|message7|2014-02-20
but should only return :
7| sw1 |user1|1|message7|2014-02-20
If I understant your question correctly, this query should return what you need:
SELECT com_msg.*
FROM com_msg INNER JOIN (SELECT MAX(msg_id) max_id
FROM com_msg
WHERE 'sw1' IN (msg_from, msg_to)
GROUP BY
CASE WHEN msg_from!='sw1' THEN msg_from
ELSE msg_to END) m
ON com_msg.msg_id = m.max_id
IDs needs to be ordered, otherwise you should use MAX(date)
Please see fiddle here.
Basically, you need to wrap this with another query, because your where clause is showing you records where either the to or the from equal the user. I'm not a MySQL guru, but you should be able to do something like this:
select top 1 *
FROM (
SELECT t1.* FROM (
SELECT MAX(msg_id) AS nr, msg_from, msg_to
FROM com_msg
GROUP BY msg_from
) AS t2
INNER JOIN com_msg t1 ON t1.msg_from=t2.msg_from AND t1.msg_id=t2.nr
WHERE t1.msg_to='sw1' OR t1.msg_from='sw1'
)
ORDER BY date DESC
This will return the most recent entry from your results based on the date.
If you are looking for just a single record returned of the last email like your example shows, this should do it...
Select TOP 1 msg_from, msg_to, msg_content, date
From com_msg
Where msg_from='sw1' OR msg_to='sw1'
ORDER BY msg_id DESC