SQL Query to get rows that have 3 unique values in column - mysql

Blanking out on how to get this data:
I have a table like this:
====================
ID | Source
====================
1 | google
1 | fb
1 | linkedIn
1 | linkedIn
3 | linkedIn
3 | fb
I want to return all the Ids that have 3 sources.
So in the above table, I want the result set to contain only id 1 since it was hit across 3 sources.
Database is mysql 5.7 so anything functions on 8.0 only won't work. Thanks for any help!

Use aggregation:
select id
from mytable
group by id
having count(distinct source) = 3

Try a query like this and see if that is helpful. It should return only IDs that have exactly 3 unique sources.
SELECT ytn.id, COUNT(DISTINCT ytn.source) AS unique_sources
FROM `your_table_name` ytn
GROUP BY ytn.id
HAVING COUNT(DISTINCT ytn.source) = 3;

Related

MySQL - how to get count of a single item frequency in a table of CSV values

I have a mysql table called "projects" with a single field containing CSV lists of project Ids. Assume that I cannot change the table structure.
I need a query that will allow me to quickly retrieve a count of rows that contain a particular project id, for example:
select count(*) from projects where '4' in (project_ids);
This returns just 1 result, which is incorrect (should be 3 results), but I think that it illustrates what I'm attempting to do.
CREATE TABLE `projects` (
`project_ids` varchar(255) DEFAULT NULL
);
INSERT INTO `projects` (`project_ids`)
VALUES
('1,2,4'),
('1,2'),
('4'),
('4,5,2'),
('1,2,5');
I was hoping that there might be a simple mysql function that would achieve this so that I don't have to anything complex sql-wise.
You could use this approach:
SELECT COUNT(*)
FROM projects
WHERE CONCAT(',', project_ids, ',') LIKE '%,4,%';
Or use FIND_IN_SET for a built-in way:
SELECT COUNT(*)
FROM projects
WHERE FIND_IN_SET('4', project_ids) > 0;
But, as to that which Gordon's comment alludes, a much better table design would be to have a junction table which relates a primary key in one table to all projects in another table. That junction table, based off your sample data, would look like this:
PK | project_id
1 | 1
1 | 2
1 | 4
2 | 1
2 | 2
3 | 4
4 | 4
4 | 5
4 | 2
5 | 1
5 | 2
5 | 5
With this design, if you wanted to find the count of PK's having a project_id of 4, you would only need a much simpler (and sargable) query:
SELECT COUNT(*)
FROM junction_table
WHERE project_id = 4;
You would need to use a like condition as follows
select count(*)
from projects
where concat(',',project_ids,',') like '%,4,%';

MySQL select with all where and one or more where not

Table structure and data (I know data in IP/domain fields might not make much sense, but this is for illustration purposes):
rec_id | account_id | product_id | ip | domain | some_data
----------------------------------------------------------------------------
1 | 1 | 1 | 192.168.1.1 | 127.0.0.1/test | abc
2 | 1 | 1 | 192.168.1.1 | 127.0.0.1/other | xyz
3 | 1 | 1 | 192.168.1.2 | 127.0.0.1/test | ooo
Table has unique index ip_domain combined from ip and domain fields (so records with identical values in both fields can't exist).
In each case I know values for account_id, product_id, ip, domain fields, and I need to get other rows that have the SAME account_id, product_id values and one (or both) of ip, domain values are DIFFERENT.
Example: I know that account_id=1, product_id=1, ip=192.168.1.1, domain=127.0.0.1/test (so it matches rec_id 1), I need to select records with IDs 2 and 3 (because record 2 has different domain and record 3 has different ip).
So, I used query:
SELECT * FROM table WHERE
account_id='1' AND product_id='1' AND ip!='192.168.1.1' AND domain!='127.0.0.1/test'
Of course, it returned 0 rows. Looked at mysql multiple where and where not in and wrote:
SELECT * FROM table WHERE
account_id='1' AND product_id='1' AND installation_ip NOT IN ('192.168.1.1') AND installation_domain NOT IN ('127.0.0.1/test')
My guess is that this query is identical (just formatted different way), so 0 rows again. Found some more examples too, but none worked in my case.
The syntax is correct, but you're using the wrong logical operation
SELECT *
FROM table
WHERE account_id='1' AND product_id='1' AND
(ip != '192.168.1.1' OR domain != '127.0.0.1/test')
Select * from table
Where ROWID <> myRowid
And account_id = '1'
And product_id = '1';
myRowid is the unique id given by your dbms to each record, in this case you need to retrieve it with your select statement and then pass it back when using this select. This will return all the rows with account_id = 1 and product_id = 1 except the one you have selected.
If your inputs are not defined/or if you want list then you may be look at Group By clause. Also, you may look at group_concat
Query would be something like:
SELECT ACCOUNT_ID, PRODUCT_ID, GROUP_CONCAT(DISTINCT IP||'|'||DOMAIN, ','), COUNT(1)
FROM TABLE
GROUP BY ACCOUNT_ID, PRODUCT_ID
P.S.: I dont have mysql installed hence the query syntax is not verified

MySQL 5.7 return all columns of table based on distinct column

I just upgraded to MySQL 5.7 and unfortunately for me, some of the functionality of GROUP BY is gone. I wanted to select all movies from my movies table with as long as the movies.id of type int is not a duplicate. My previous query in MySQL 5.6 was:
SELECT *
FROM movies
WHERE movies.title LIKE '%example%'
GROUP BY movies.id
If I had two movies with the same id, it would only display one movie, instead of that movie and its duplicates.
When I upgraded to MySQL 5.7, the GROUP BY gave me errors and I was instead told to use ORDER BY. However this query:
SELECT *
FROM movies
WHERE movies.title LIKE '%example%'
ORDER BY movies.id
Does return duplicate movies. So, is there a way to filter this out, and only return a row if it isn't a duplicate?
Edit: For example if this is my movies table:
movies
==================
| id | title |
==================
| 1 | example |
------------------
| 2 | example |
------------------
| 1 | example |
------------------
Here is the output of each query:
Previous query result (with MySQL 5.6)
=======
1 | example
2 | example
New query result (with MySQL 5.7 and ORDER BY)
=======
1 | example
1 | example
2 | example
I want the final result to contain no duplicates (so the result should look like the first query result).
Edit 2: I understand I was sort of abusing the way MySQL handled GROUP BY. Unfortunately, I do not have much experience with MySQL and got that answer from StackOverflow. I would just like to return all columns in my table that do not contain duplicate ids.
I believe would be easy to use distinct keyword
SELECT distinct movies.*
FROM movies
WHERE movies.title = 'example'

MySQL counting number of max groups

I asked a similar question earlier today, but I've run into another issue that I need assistance with.
I have a logging system that scans a server and catalogs every user that's online at that given moment. Here is how my table looks like:
-----------------
| ab_logs |
-----------------
| id |
| scan_id |
| found_user |
-----------------
id is an autoincrementing primary key. Has no real value other than that.
scan_id is an integer that is incremented after each successful scan of all users. It so I can separate results from different scans.
found_user. Stores which user was found online during the scan.
The above will generate a table that could look like this:
id | scan_id | found_user
----------------------------
1 | 1 | Nick
2 | 2 | Nick
3 | 2 | John
4 | 3 | John
So on the first scan the system found only Nick online. On the 2nd it found both Nick and John. On the 3rd only John was still online.
My problem is that I want to get the total amount of unique users connected to the server at the time of each scan. In other words, I want the aggregate number of users that have connected at each scan. Think counter.
From the example above, the result I want from the sql is:
1
2
2
EDIT:
This is what I have tried so far, but it's wrong:
SELECT COUNT(DISTINCT(found_user)) FROM ab_logs WHERE DATE(timestamp) = CURDATE() GROUP BY scan_id
What I tried returns this:
1
2
1
The code below should give you the results you are looking for
select s.scan_id, count(*) from
(select distinct
t.scan_id
,t1.found_user
from
tblScans t
inner join tblScans t1 on t.scan_id >= t1.scan_id) s
group by
s.scan_id;
Here is sqlFiddle
It assumes the names are unique and includes current and every previous scans in the count
Try with group by clause:
SELECT scan_id, count(*)
FROM mytable
GROUP BY scan_id

export phpList subscribers via sql in mysql database

For some reason, I am unable to export a table of subscribers from my phpList (ver. 3.0.6) admin pages. I've searched on the web, and several others have had this problem but no workarounds have been posted. As a workaround, I would like to query the mySQL database directly to retrieve a similar table of subscribers. But I need help with the SQL command. Note that I don't want to export or backup the mySQL database, I want to query it in the same way that the "export subscribers" button is supposed to do in the phpList admin pages.
In brief, I have two tables to query. The first table, user contains an ID and email for every subscriber. For example:
id | email
1 | e1#gmail.com
2 | e2#gmail.com
The second table, user_attribute contains a userid, attributeid, and value. Note in the example below that userid 1 has values for all three possible attributes, while userid's 2 and 3 are either missing one or more of the three attributeid's, or have blank values for some.
userid | attributeid | value
1 | 1 | 1
1 | 2 | 4
1 | 3 | 6
2 | 1 | 3
2 | 3 |
3 | 1 | 4
I would like to execute a SQL statement that would produce a row of output for each id/email that would look like this (using id 3 as an example):
id | email | attribute1 | attribute2 | attribute3
3 | e3#gmail.com | 4 | "" | "" |
Can someone suggest SQL query language that could accomplish this task?
A related query I would like to run is to find all id/email that do not have a value for attribute3. In the example above, this would be id's 2 and 3. Note that id 3 does not even have a blank value for attributeid3, it is simply missing.
Any help would be appreciated.
John
I know this is a very old post, but I just had to do the same thing. Here's the query I used. Note that you'll need to modify the query based on the custom attributes you have setup. You can see I had name, city and state as shown in the AS clauses below. You'll need to map those to the attribute id. Also, the state has a table of state names that I linked to. I excluded blacklisted (unsubscribed), more than 2 bounces and unconfirmed users.
SELECT
users.email,
(SELECT value
FROM `phplist_user_user_attribute` attrs
WHERE
attrs.userid = users.id and
attributeid=1
) AS name,
(SELECT value
FROM `phplist_user_user_attribute` attrs
WHERE
attrs.userid = users.id and
attributeid=3
) AS city,
(SELECT st.name
FROM `phplist_user_user_attribute` attrs
LEFT JOIN `phplist_listattr_state` st
ON attrs.value = st.id
WHERE
attrs.userid = users.id and
attributeid=4
) AS state
FROM
`phplist_user_user` users
WHERE
users.blacklisted=0 and
users.bouncecount<3 and
users.confirmed=1
;
I hope someone finds this helpful.