There might be an easy solution here, but it seems to have me tripped up. I'm trying to query a table based on an array of values in two columns. Here is the pertinent table structure and sample data
comment table
id, userId, articleId .... etc etc
article table
id, userId .... etc etc
Data: UserIds = 3, 10. ArticleIds = 1, 2
Let's say I'm trying to find all the comments for a particular set of article IDs: 1,2
I can easily use this query
select * from comments WHERE articleId IN(1,2)
However, here is where it gets complex. I have a query that executes prior to the comments query that determines the appropriate article IDs. Those IDs are in an array. Also in an array are the corresponding user IDs for each article.
What I want to do now is query the comments table for only the articles in the array (1,2) AND only for those comments made by the original author (3, 10).
The simple query above will bring back all the comments for articleId 1 and 20. So for example I can't figure out where to add another conditional that says onyl comments for articleId 1, 20 AND corresponding userId, 3, 10.
Any help or suggestions would be much appreciated!
I think the simplest way is to write:
SELECT comments.*
FROM articles
JOIN comments
ON articles.id = comments.articleId
AND articles.userId = comments.userId
WHERE articles.id IN (1, 2)
;
The AND articles.userId = comments.userId clause is what enforces your "only for those comments made by the original author" requirement.
Alternatively, you can use an EXISTS clause:
SELECT *
FROM comments
WHERE articleId IN (1, 2)
AND EXISTS
( SELECT 1
FROM articles
WHERE id = comments.articleId
AND userId = comments.userId
)
;
or a single-row subquery:
SELECT *
FROM comments
WHERE articleId IN (1, 2)
AND userId =
( SELECT userId
FROM articles
WHERE id = comments.articleId
)
;
Have you tried just
select * from comments WHERE articleId IN(1,2) and authorId in (3,10)
If not, please update your question why it's so.
You can add as many IN statements as you want:
select * from comments WHERE articleId IN(1,2) AND userId IN (3,10)
Can't you just make the query that runs first a subquery within your stated query:
SELECT * FROM `comments` WHERE `articleId` IN(1,2) AND `userId` IN (__subquery__)
-- you can use subquery
select * from comments WHERE articleId IN(1,2)
and userId in ( select userId from article where id in (1,2) )
Related
I have two tables, one for registered users and one to store votes.
We are logging in with registrants.id and registrants.zipcode. Once they vote their votes are inserted into the votes table, along with their Registration ID.
Im trying to right a select statement that returns a record that will select all the records for Matched ID and Zipcode, but the ID is not in the Votes.voter column. i have tried all kinds of variations of all the joins i can think of. is it something simple i am missing.
SELECT * FROM registrants
LEFT JOIN votes on registrants.id = votes.voter
WHERE registrants.id = 1 AND registrants.zipcode = 46706 and votes.voter <> 1
Perhaps a not exists query:
select * from registrants
where registrants.zipcode = '46706'
and not exists (select 1 from votes where registrants.id = votes.voter)
I am performing MySQL functions using PHP for my webpages.
I have got a table
table name -> users
uname oname
john alex
john murray
john joseph
john ray
and another table
table name -> more_info
fname lname more
alex some name some info
murray // //
joseph // //
ray // //
What I am trying to do is to run a query
Retrieve all the oname column values which are matched with uname john
This statement successfully retrieves the oname column values if uname = john
SELECT oname FROM users WHERE uname = 'john '
Now I want a statement something like this, based on the previously retrieved oname column values
SELECT * FROM more_info WHERE fname=oname // previos ones
I guess its Join orinnerJoin but somehow I am unable to get the correct syntax of it or any other simple query to do this.
My approach
I thought to retrieve the oname column values first and then inside a for loop, based on number of rows returned run a query for each column, but this approach eats up my server.
Try this query,
SELECT * FROM `more_info` `i` INNER JOIN `users` `u` ON `i`.`fname`=`u`.`oname` WHERE `u`.`uname`="john"
I think the following query wll help u.
SELECT * FROM `more_info` WHERE `fname` = (SELECT `oname` FROM `users` WHERE `uname` = "john")
You can merge your two queries into one by a simple INNER JOIN
SELECT * FROM more_info mi
INNER JOIN users u ON mi.fname = u.oname
WHERE u.uname = 'john'
If there is some chance of null values in more_info table, then you should use LEFT JOIN instead of INNER JOIN. Otherwise it is not necessary.
SELECT * FROM users A
INNER JOIN more_info B
ON A.oname = B.fname
WHERE uname = 'john'
See the MySQL documentation on the JOIN syntax for details.
How can I select one row from that table http://i.stack.imgur.com/27cu9.jpg where values of 'user_1' and 'user_2' may look like
user_1 user_2
1 2
2 1
In other words I want to select a field that contains 2 users with submitted=1 no matter in which field the value is.
Here is a simple query that does this:
select *
from t
where submitted = 1 and 2 in (user_1, user_2)
If I understood your question, I think you need to JOIN the table on itself if you are trying to return rows that have corresponding users (1,2) and (2,1):
select t1.*
from yourtable t1
join yourtable t2 on
t1.user_1 = t2.user_2 and t1.user_2 = t2.user_1
SQL Fiddle Demo
If however you are just trying to see if user 2 exists in either of the fields, then look at Gordon's post.
Use this:-
select * from tblname as t1, tblname as t2 where
t1.user_1 = t2.user_2 and t1.user_2 = t2.user_1 and t1.user_1<>t1.user_2
EDIT:-
Updated the query so that the rows with the same values do not appear in the result.
How do I select a column value as a column name and group the results as a row.
I have a table as such:
id articleId label value
1 1 title Example title
2 1 description This is the description
3 1 author Me
4 2 title Example of another type of article
5 2 description Short description
6 2 author Someone else
Is it possible to select all of the rows and use the label as the column name and the value as the value of that column name and then group them by the article name.
So how I would like to have it returned:
articleId title description author
1 Example title This is the.. Me
2 Example of an.. Short descr.. Someone else
I'm using this for a CMS where the user can define the fields for an article so we don't have to customize the table's. This is why i'm not making the tables as the I would like to have it returned. I am also aware that I can just as easily convert the result to this in php.
-- edit --
Can this be done without knowing what labels are added? In this example im using title, description and author. But it could very well be something totally different like title, shortDescription, availableTo, techInformation, etc.. The idea is that the article's are customizable for the user without needing to change the database and query's
I figured I'd better post as an answer, even if not what OP would like to hear. What you are asking to do is to populate a query with a variable number of columns based on the distinct values within column label, all associated with articleID. Taking your specific example, the following would be the resultant query that I would most likely go to in this instance (though the example from #Devart is equally valid)
SELECT
t.id,
t.articleId,
t1.value AS title,
t2.value AS description,
t3.value AS author
FROM `tableName` t
LEFT JOIN `tablename` t1
ON t1.article_id = t.article_id AND t1.label = 'title'
LEFT JOIN `tablename` t2
ON t2.article_id = t.article_id AND t2.label = 'description'
LEFT JOIN `tablename` t3
ON t3.article_id = t.article_id AND t3.label = 'author'
Now expanding this to account for up to n labels, we get the following query (metacode included, this query will NOT execute verbatim)
SELECT DISTINCT label FROM `tableName`;
SELECT
t.id,
t.articleId
// for (i=1;i<= number of distinct labels) {
,t[i].value AS [value[i]]
// }
FROM `tableName` t
// for (i=1;i<= number of distinct labels) {
LEFT JOIN `tablename` t[i]
ON t[i].article_id = t.article_id AND t[i].label = [value[i]]
// }
;
So what you can do is one of the following.
SELECT t.* FROM tablename t and then have PHP process it as required
SELECT DISTINCT label FROM tablename and have PHP build the second query with the many LEFT JOINs (or MAX / GROUP BY logic if preferred)
Create a Stored Procedure to do the same as #2. This would most likely be more efficient than #2 however may be less efficient overall than #1.
You can use pivote table trick -
SELECT
articleId,
MAX(IF(label = 'title', value, NULL)) AS title,
MAX(IF(label = 'description', value, NULL)) AS description,
MAX(IF(label = 'author', value, NULL)) AS author
FROM
table
GROUP BY
articleId
Try below :
select t1.articleId,t1.title,t1.description,t1.author
from tablename as t1
left join (select max(articleId) as articleId
from tablename
group by articleId ) as t2
on t1.articleId=tsm.articleId where [.....]
Hi I have a table like this
ID UserName
1 test#test.com
2 test#test.com
3 john#stack.com
4 test#test.com
5 adam#stack.com
6 john#stack.com
I need an output like this. I need only repeated rows list. How can I create this kind of an output using mysql query.
ID UserName Count
1 test#test.com 3
2 john#stack.com 2
Please help me.
Thanks.
I had the same problem some time ago and solved it like this (as far as I remember):
SELECT *
FROM tableA INNER JOIN
(SELECT DISTINCT MAX(id) as id, type_id, temp FROM tableA GROUP BY type_id, temp) AS t
ON tableA.id = t.id
AND tableA.type_id = t.type_id
AND tableA.temp = t.temp
You join the table with itself selecting the ids that are duplicate. The fields that should be tested against duplicate values are in this case type_id and temp. If you need more or less fields that should be considered as duplicates you can adjust the fields.
I don't know if this helps in your case and if it can be done in a more simple way, so I'm prepared for downvotes ;-)
Edit: removed last condition AND tableA.id < t.id as suggested by ypercube because it leads to 0 results.
It looks like you're trying to pull the following data:
First ID for a given UserName
The UserName itself
The total number of IDs for that UserName
This query should do the trick:
SELECT
MIN(id),
UserName,
COUNT(id)
FROM users
GROUP BY UserName;
since the ID is not unique so its a bit not logical to get the sum of unique UserName from the table.
If the ID is not required we can get the result from single query.
SELECT UserName, COUNT(UserName) AS Count
FROM TableName GROUP BY UserName
HAVING COUNT(UserName) > 1;
But in the case of ID in the result it will be a more complicated query including sub-query and inner table.
SELECT UserName
, COUNT(*) AS `Count`
FROM tableX
GROUP BY UserName
HAVING COUNT(*) > 1
Hi this is the right answer.
SELECT UserName, COUNT(UserName) AS Count
FROM TableName GROUP BY UserName
HAVING COUNT(UserName) > 1;