Mysql select complex query - php

I am sorry for the vague title but I really cannot make this any more specific with my English.
I have this table called posts__tags that I use to associate post ids and tag ids with the following columns
record_id, post_id and tag_id. Here is an example sample
record_id | post_id | tag_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 2
5 | 3 | 1
6 | 3 | 3
7 | 4 | 2
8 | 4 | 3
9 | 4 | 4
I have a php function that has an array of tag_ids as a parameter. Lets say for example that my parameter is the array(2,3). I need to select all the post_id's that are associated with tag_id = 2 AND tag_id = 3.
In the above example I should get the 1 and 4 post_id's since only those are associated with both 2 and 3 tag_id 's.
What is the best way to achieve that with a MySQL query?
Thanks in advance

select post_id from posts__tags where tag_id in (1,2) group by post_id having count(*)=2

Try this
select distinct post_id from table_name where tag_id in (2,3)

Related

Using LIMIT within GROUP BY to get N results per dynamic group

Using LIMIT within GROUP BY to get N results per dynamic group
Hello everyone, firstly I read about questions like this problem.
But didn't get the solution. All of this SQL's are designed for static columns.
But I have dynamic columns.
Table:
id Name Group Level
2 Jonathan A 5
5 David A 10
6 Alex C 10
7 Kemal A 71
8 John D 21
9 Celin F 100
12 Alexis G 15
13 Noone A 23
I want to get the first 2 highest Level from each group.
But query must be dynamic because there will be more Groups, which is where I am stuck.
Solutions I tried:
Select the top N rows from each group Not giving true result it's broken.
Only work in static columns.
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,name VARCHAR(12) NOT NULL
,group_name CHAR(1) NOT NULL
,level INT NOT NULL
);
INSERT INTO my_table VALUES
( 2,'Jonathan','A',5),
( 5,'David','A',10),
( 6,'Alex','C',10),
( 7,'Kemal','A',71),
( 8,'John','D',21),
( 9,'Celin','F',100),
(12,'Alexis','G',15),
(13,'Noone','A',23);
SELECT id
, name
, group_name
, level
FROM
( SELECT x.*
, CASE WHEN #prev = group_name THEN #i:=#i+1 ELSE #i:=1 END i
, #prev:=group_name
FROM my_table x -- technically, ordering should really happen here, in a separate subquery
, ( SELECT #prev:=null,#i:=0 ) vars
ORDER
BY group_name
, level DESC
, id
) a
WHERE i <=2;
+----+--------+------------+-------+
| id | name | group_name | level |
+----+--------+------------+-------+
| 7 | Kemal | A | 71 |
| 13 | Noone | A | 23 |
| 6 | Alex | C | 10 |
| 8 | John | D | 21 |
| 9 | Celin | F | 100 |
| 12 | Alexis | G | 15 |
+----+--------+------------+-------+
You can also do workaround.
Select colums upto 2 rows
FROM TABLE ORDER BY DESCENDING GROUP LEVEL
regards,
Umar Abdullah

SQL Query field same ID

I have a mySQL table like this example:
ID | ProcID | Value
1 | 6 | one
1 | 7 | two
1 | 8 | three
1 | 9 | four
2 | 6 | one
2 | 7 | two
2 | 8 | three
2 | 9 | four
I need to get only the ID #1 and the value from the ProcID 6 and 7.. how can I do with only one PHP query?
I already did with two separate queries but I'm sure is possible with only one, maybe with some parameters such "ON" or "IN" but I didn't find anything!
Try this:
SELECT *
FROM table
WHERE ID = 1 AND ProcID IN (6,7)
Sample result:
ID | ProcID | Value
--------------------
1 | 6 | one
1 | 7 | two
If you want to select the only ID of 1 from ProcID use :
SELECT * FROM `table` where `ID` = '1' AND `ProcID` = '6' AND `ProcID` = '7'

Want to execute one complex Mysql query [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 9 years ago.
I want to get the result set only by one query if possible
i have table like that
------------------------------
user_id | activity_id | score
------------------------------
1 | 1 | 100
------------------------------
1 | 1 | 50
------------------------------
1 | 2 | 20
------------------------------
1 | 3 | 10
------------------------------
1 | 3 | 50
------------------------------
2 | 1 | 300
------------------------------
3 | 3 | 10
------------------------------
3 | 2 | 40
------------------------------
All what i need to select each user with sum of all of his high score in each activity.
for example the result set should be like that:
------------------------------
user_id | score
------------------------------
1 | 170
------------------------------
2 | 300
------------------------------
3 | 50
------------------------------
To get the highest score for each user/activity pair, you would use the following query:
select user_id, activity_id, max(score) as highscore
from t
group by user_id, activity_id;
To add these up for a given user, you would make this a subquery and do another aggregation:
select user_id, sum(highscore)
from (select user_id, activity_id, max(score) as highscore
from t
group by user_id, activity_id
) t
group by user_id;

mysql query returning issue while using the comparison

I have a table with two fields
---------------
Qn | ans
---------------
1 | 2
---------------
1 | 4
---------------
1 | 6
---------------
1 | 8
---------------
2 | 2
---------------
2 | 4
---------------
2 | 6
---------------
if am using the query to get the result as '1' but because of the value in 2 its returning 1 and 2.
SELECT qn FROM tbl T1 WHERE T1.ans IN (2,4,6,8)
i need the result 1 , is there any other method to get the result
SELECT qn
FROM tbl
WHERE ans IN (2,4,6,8)
group by qn
having count(distinct ans) = 4

Skip 0 and NULL in SQL

My previous problem and solution:
Get max and min from fields
This working OK, but i would like skip 0 and NULL in this examples.
For example:
First:
id | title
1 | aaa
2 | bbb
3 | ccc
Second:
id | first_id | one | two | three | four
1 | 1 | 3 | 0 | 4 | 6
2 | 2 | 4 | 4 | 1 | 2
3 | 3 | 1 | NULL | 3 | 4
this should show me:
id | title | min | max
1 | aaa | 3 | 6
2 | bbb | 1 | 4
3 | ccc | 1 | 4
and not:
id | title | min | max
1 | aaa | 0 | 6
2 | bbb | 1 | 4
3 | ccc | 0 | 4
In which example from my previous question is the best way to implement skip 0 and NULL?
Pop these into your clause
SELECT
f.id,
f.title
MIN(LEAST(greatest(coalesce(s.one,0),1), greatest(coalesce(s.two,0),1), greatest(coalesce(s.three,0),1), greatest(coalesce(s.four,0),1))) as min,
MAX(GREATEST(greatest(coalesce(s.one,0),1), greatest(coalesce(s.two,0),1), greatest(coalesce(s.three,0),1), greatest(coalesce(s.four,0),1))) as max
FROM
First f
INNER JOIN Second s
on f.id = s.first_id
GROUP BY
f.id,
f.title
You can use coalesce(fieldName, 1) to turn a null into a 1.
Again, as said in your previous question, this is HORRIBLE use of a query to force an answer. You should be changing the layout of the database.
Edit: I have nutted out the data you want, but before you look at it, be aware that if one of my colleagues wrote a script like this, he would be sacked on the spot. This is HIDEOUS and should NOT BE USED.
select
f.id,
f.title,
(select min(z.myVal) from
(
select
b.id,
b.first_id,
b.one as myVal
from
second b
where
b.one is not null
and b.one > 0
union
select
b.id,
b.first_id,
b.two as myVal
from
second b
where
b.two is not null
and b.two > 0
union
select
b.id,
b.first_id,
b.three as myVal
from
second b
where
b.three is not null
and b.three > 0
union
select
b.id,
b.first_id,
b.four as myVal
from
second b
where
b.four is not null
and b.four > 0
) z
where
f.id=z.first_id) as miniVal,
greatest(
coalesce(s.one,0),
coalesce(s.two,0),
coalesce(s.three,0),
coalesce(s.four,0)
) as maxiVal
from
first f,
second s
where
f.id=s.first_id
output Data
+------+-------+---------+---------+
| id | title | miniVal | maxiVal |
+------+-------+---------+---------+
| 1 | aaaa | 3 | 6 |
| 2 | bbbb | 1 | 4 |
| 3 | cccc | 1 | 4 |
+------+-------+---------+---------+
3 rows in set (0.00 sec)
Running this query made me throw up a little in my mouth. That's how wrong it is to write SQL like this.
While seemingly clunky, this solution should work:
SELECT
a.id, a.title, MIN(b.num) AS min, MAX(b.num) AS max
FROM
first a
LEFT JOIN
(
SELECT first_id, one AS num FROM second UNION ALL
SELECT first_id, two FROM second UNION ALL
SELECT first_id, three FROM second UNION ALL
SELECT first_id, four FROM second
) b ON
a.id = b.first_id AND
b.num IS NOT NULL AND
b.num > 0
GROUP BY
a.id, a.title
What this does is it actually gets each number column into its own row, but only the numbers that are not null and > 0. Before the GROUP BY, the result of the LEFT JOIN would look something like:
id | title | num
---------------------
1 | aaa | 3
1 | aaa | 4
1 | aaa | 6
2 | bbb | 1
2 | bbb | 2
2 | bbb | 4
2 | bbb | 4
3 | ccc | 1
3 | ccc | 3
3 | ccc | 4
Then by the groupings of each first (GROUP BY a.id, a.title), we can use the MIN() and MAX() aggregate functions on the num column to extract minimum and maximum values per first group:
id | title | min | max
----------------------------
1 | aaa | 3 | 6
2 | bbb | 1 | 4
3 | ccc | 1 | 4
In the case that a first_id had all four columns having NULL's or 0's, the min and max values would show up as NULL due to using a LEFT JOIN instead of an INNER JOIN as I believe this is would be a better behavior for your situation:
id | title | min | max
----------------------------
4 | ddd | NULL | NULL
USE:
WHERE COLUMN IS NOT NULL AND COLUMN <> 0;
I think you just need to nest the LEAST expressions:
LEAST(
NULLIF(one,0),
LEAST(
NULLIF(two,0),
LEAST(
NULLIF(three,0),
LEAST(
NULLIF(four,0),
null ))))
Edit I just looked it up. The LEAST function takes multiple arguments:
LEAST( NULLIF(one,0), NULLIF(two,0), NULLIF(three,0), NULLIF(four,0))
Edit 2 I see you want both min and max. Obviously you'd just change LEAST to GREATEST or MIN to MAX as needed.
This may be more straightforward or you may not have a handy least function.
SELECT
f.id, f.title,
(
SELECT MIN(NULLIF(val, 0))
FROM
(
SELECT one AS val UNION ALL
SELECT two UNION ALL
SELECT three UNION ALL
SELECT four
) AS vals
)
) as minval
FROM First f INNER JOIN Second s on f.id = s.first_id
You haven't specified if it's possible for all four columns to be null/0. We may need to tweak for that case.
You can use IFNULL():
WHERE IFNULL(fieldname, 0) != 0

Categories