I have a table like this:
id | customer_id | code
-----------------------
1 | 1 | A
2 | 1 | B
3 | 2 | A
4 | 2 | D
5 | 3 | B
6 | 3 | C
6 | 3 | D
I need an SQL query that returns all customer ids with codes equal to A and B. In the above data, this would only be customer_id 1.
If the codes were each their own column, this would be a straightforward query: SELECT DISTINCT customer_id FROM tablename WHERE code = A AND code = B. I can't seem to craft it over multiple rows, however.
You can use a GROUP BY customer_id with a HAVING clause:
select customer_id
from yourtable
where code in ('A', 'B')
group by customer_id
having count(distinct code) = 2
See SQL Fiddle with Demo
If you want to return more data from your table, then you can expand the query to:
select *
from yourtable t1
where exists (select customer_id
from yourtable t2
where code in ('A', 'B')
and t1.customer_id = t2.customer_id
group by customer_id
having count(distinct code) = 2)
See SQL Fiddle with Demo
select customer_id
from tablename
where code in ('A', 'B')
group by customer_id
having count(*) > 1
Related
There are a lot of questions dealing with max values but I can't find any that relate to this issue.
ID | Company | Result
----------------------
1 | 1 | A
2 | 1 | C
3 | 1 | B <--
4 | 2 | C
5 | 2 | B
6 | 2 | A <!--
7 | 3 | C
8 | 3 | A
9 | 3 | B <--
I need to output the Companies whose last Result (based on ID) was "B".
To further complicate the issue, the $query will be used this:
select * from table where Company in ($query)
Any ideas? Thanks!
On MySQL 8+, here is a query you may try using analytic functions:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Company ORDER BY ID DESC) rn
FROM yourTable
)
SELECT ID, Company, Result
FROM cte
WHERE rn = 1 AND Result = 'B';
Demo
On earlier versions of MySQL, we can try joining to a subquery which finds the most recent record for each company:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT Company, MAX(ID) AS MAX_ID
FROM yourTable
GROUP BY Company
) t2
ON t1.Company = t2.Company AND
t1.ID = t2.MAX_ID
WHERE
t1.Result = 'B';
Demo
My table:
id | request | subject | date
1 | 5 | 1 | 576677
2 | 2 | 3 | 576698
3 | 5 | 1 | 576999
4 | 2 | 3 | 586999
5 | 2 | 7 | 596999
Need to select unique records by two columns(request,subject). But if we have different pairs of request-subject(2-3, 2-7), this records should be excluded from resulted query.
My query now is:
SELECT MAX(id), id, request, subject, date
FROM `tbl`
GROUP BY request, subject
having count(request) > 1
order by MAX(id) desc
How to exclude record with id=4, id=5 from this query? Thanks!
You may group by request, and then check for every group if all subjects in it are equal. You could do it using MIN() and MAX():
SELECT request, MIN(subject) AS subject
FROM table_1
GROUP BY request
HAVING MIN(subject) = MAX(subject)
As for your update, I assume you want all the fields for the max ID in the group (in your example, ID 3). The query would then look like this one:
SELECT *
FROM table_1 t
WHERE t.id IN (SELECT MAX(s.id)
FROM table_1 s
GROUP BY s.request
HAVING MIN(s.subject) = MAX(s.subject))
ORDER BY t.id
You can try this.
select * from MyTable T1
WHERE NOT EXISTS( SELECT * FROM MyTable T2
WHERE T1.id <> T2.id
and T1.request = T2.request
and T1.subject <> T2.subject)
Sql Fiddle
I am a SQL beginner and am learning the ropes of querying. I'm trying to find the date difference between purchases by the same customer. I have a dataset that looks like this:
ID | Purchase_Date
==================
1 | 08/10/2017
------------------
1 | 08/11/2017
------------------
1 | 08/17/2017
------------------
2 | 08/09/2017
------------------
3 | 08/08/2017
------------------
3 | 08/10/2017
I want to have a column that shows the difference in days for each unique customer purchase, so that the output will look like this:
ID | Purchase_Date | Difference
===============================
1 | 08/10/2017 | NULL
-------------------------------
1 | 08/11/2017 | 1
-------------------------------
1 | 08/17/2017 | 6
-------------------------------
2 | 08/09/2017 | NULL
-------------------------------
3 | 08/08/2017 | NULL
-------------------------------
3 | 08/10/2017 | 2
What would be the best way to go about this using a MySQL query?
Not so hard, just use a subquery to find previous purchase for each existing purchase for the customer, and self-join to that record.
Select t.id, t.PurchaseDate, p.Purchase_date,
DATEDIFF(t.PurchaseDate, p.Purchase_date) Difference
From myTable t -- t for This purchase record
left join myTable p -- p for Previous purchase record
on p.id = t.Id
and p.purchase_date =
(Select Max(purchase_date)
from mytable
where id = t.id
and purchase_date <
t.purchaseDate)
This is rather tricky in MySQL. Probably the best way to learn if you are a beginning is the correlated subquery method:
select t.*, datediff(purchase_date, prev_purchase_date) as diff
from (select t.*,
(select t2.purchase_date
from t t2
where t2.id = t.id and
t2.purchase_date < t.purchase_date
order by t2.purchase_date desc
limit 1
) as prev_purchase_date
from t
) t;
Performance should be okay if you have an index on (id, purchase_date).
It is possible to solve it not using dependent subquery
SELECT yt.id, create_date, NULLIF(yt.create_date - tm.min_create_date, 0)
FROM your_table yt
JOIN
(
SELECT id, MIN(create_date) min_create_date
FROM your_table
GROUP BY id
) tm ON tm.id = yt.id
sqlfiddle demo
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.
I have a sample data with table is test
name | catid | date
------------
abc | 1
def | 2
ghi | 1
jkl | 2
mno | 1
pqr | 3
And my query
SELECT * FROM test WHERE catid = 1 AND catid = 2 AND catid = 3 ORDER BY date DESC
How to get value with result is
name | catid
------------
abc | 1
def | 2
pqr | 3
SELECT a.*
FROM TableName a
INNER JOIN
(
SELECT catid, MAX(DATE) max_date
FROM tableName
GROUP BY catID
) b ON a.catID = b.catID AND
a.date = b.max_date
SELECT name, catid FROM test WHERE catid IN (1, 2, 3) GROUP BY catid
I think you need the IN operator which is simplier than catid = X OR catid... (and you need OR, not AND)
Based on your desired output, this might be the query:
select catid, min(name)
from yourtable
where catid between 1 and 3
group by catid
But it's hard to know what you want based on the info provided in your question.