PHP order by clause with array as order by statement - mysql

I got a array with a query
This array is ordered by criteria.
Now I want to make a new query
Sample
$array = (987, 2661, 12, 789, 54);
And I want in this order by array selecting articles
select * from article a.number WHERE (a.number IN ($array))
How can I realize that this result is ordered by $array ids?
Thx you 4 answer guys :)
edit :
Article Table:
id, name etc..
Property Table:
id, article_id, name, value
1, 10, journey_days, 2
2, 30, journey_days, 1
3, 40, journey_days, 5
1, 10, stars, 2
2, 10, stars, 4
3, 10, stars, 0
4, 10, stars, 1
I join both tables, but as you can see the property have more then one value per column for one article.
I need to join the Property table to the article table and get all Values there are related from property table to the article, if I make a where clause I just get stars or journey_days.
How can I realise this? to select all property.name values with a where or on clause?
Hope you guys understand my question

Use implode:
$s = implode(",", $array);
$q = "select * from article a.number WHERE (a.number IN ($s))";

You could construct a CASE expression and order by that, but it's probably better to do this in PHP, outside of the database.
... ORDER BY CASE a.number
WHEN 987 THEN 1
WHEN 2661 THEN 2
WHEN 12 THEN 3
WHEN 789 THEN 4
WHEN 54 THEN 5
END;
Or you could use the FIND_IN_SET function:
.... ORDER BY FIND_IN_SET(a.number, "987,2661,12,789,54");

Related

MySQL update multiple rows using arrays

How can we update multiple rows at once in case of below stated data
studentId = [1,2,5,7,9]
marks = [25, 22, 27, 30, 24]
what will be the MySQL statement, if we want to update studentId 1 with 25 marks, studentId 2 with 22 marks, studentId5 with 27 marks and so on.
Please note: Have to update in 1 query only.
Thanks in advance :)
If you are using MySql 8.0+ you can create a CTE that returns the rows of the ids that you want to update and their marks and join it to the table:
WITH cte(studentId, marks) AS (VALUES
ROW(1, 25), ROW(2, 22), ROW(5, 27), ROW(7, 30), ROW(9, 24)
)
UPDATE tablename t
INNER JOIN cte c ON c.studentId = t.studentId
SET t.marks = c.marks
See the demo.
For previous versions, instead of the CTE you can join a query that uses UNION ALL:
UPDATE tablename t
INNER JOIN (
SELECT 1 studentId, 25 marks UNION ALL
SELECT 2, 22 UNION ALL
SELECT 5, 27 UNION ALL
SELECT 7, 30 UNION ALL
SELECT 9, 24
) c ON c.studentId = t.studentId
SET t.marks = c.marks
See the demo.
You could run one simple query five times, with different values:
UPDATE MyTable SET marks = ? WHERE studentId = ?
The idea is that you would write a loop in some application code, so you process the first element from each of your arrays. Then the second element of both arrays, and so on. For example in PHP:
$studentId = [1,2,5,7,9];
$marks = [25, 22, 27, 30, 24];
$stmt = $pdo->prepare("UPDATE MyTable SET marks = ? WHERE studentId = ?");
for ($i=0; $i<5; ++$i) {
$stmt->execute([$marks[$i], $studentId[$i]]);
}
From its earliest versions, SQL was always intended to be used in combination with an application language. Other languages have variables and loops and conditions and functions, which complement SQL. The easiest solution is to use these languages together.
If you really want to write a single UPDATE statement to update all five, it's possible, but it's really not as clear.
UPDATE MyTable
SET marks = CASE studentId
WHEN 1 THEN 25
WHEN 2 THEN 22
WHEN 5 THEN 27
WHEN 7 THEN 30
WHEN 9 THEN 24
END
WHERE studentId IN (1,2,5,7,9);
There are other clever ways of doing it in one statement, but all these solutions are hard to modify or maintain. They are needlessly complex.
I recommend doing it the simple way.

MySQL get all rows in which one field belongs to array, and all members have a common value in the other field

Let's say I have the following table of user properties:
id, user_id properties
1, NULL, prop_ss1
2, NULL, prop_ss2
3, 2, prop_1
4, 2, prop_2
5, 3, prop_1
6, 3, prop_2
7, 3, prop_3
8, 4, prop_1
Given an array of user_ids, how could I get the list of all properties which either have the user_id NULL (call it a global property if you wish), or are shared among all user_ids in the given array?
For instance, given an array (2,3), I would like to get:
prop_ss1
prop_ss2
prop_1
prop_2
Or, given an array(2,3,4), I would like to get:
prop_ss1
prop_ss2
prop_1
Try a UNION of two separate queries:
SELECT properties FROM your_table WHERE user_id IS NULL
UNION
SELECT properties
FROM your_table
WHERE user_id IN (2, 3)
GROUP BY properties
HAVING COUNT(DISTINCT user_id) = 2
See it working online: sqlfiddle
The number 2 in the last line is the number of users that you are querying for.
select distinct properties from table
where user_id is null
or user_id in (1,2,3)
Sorry misread your post, need group by and having

How do I create a query that caters for two different groups of data and produces a result that is dependent on the first set in MySQL?

I'm trying to count all instances where a group of data has one or more fail.
I'm also Finding it very difficult to build this question so I'm hoping that showing an example will do the trick in explaining what I'm trying to achieve.
Sample data:
INSERT INTO test.answers (id, result_id, fail_all, fail_group) VALUES
(1,1,0,1), (2,1,0,1), (3,1,0,1), (4,1,0,0),
(5,2,1,0), (6,2,0,0), (7,2,1,0), (8,2,1,0), (9,2,1,0),
(10,3,0,1), (11,3,1,1), (12,3,0,1), (13,3,0,1), (14,3,0,1),
(15,4,0,0), (16,4,0,0), (17,4,0,1), (18,4,0,1), (19,4,0,0), (20,4,0,1),
(21,5,1,0), (22,5,0,1), (23,5,1,1), (24,5,0,1), (25,5,1,0), (26,5,0,1);
INSERT INTO test.results (id,team_id) VALUES
(1,1), (2,1), (3,1), (4,2), (5,2);
I then run the following query:
SELECT
COUNT(IF(a.fail_all = 1,1,NULL)) AS count_fail_all,
COUNT(IF(a.fail_group = 1,1,NULL)) AS count_fail_group,
a.result_id
FROM test.answers AS a
GROUP BY a.result_id
Result:
count_fail_all, count_fail_group, result_id
0, 3, 1
4, 0, 2
1, 5, 3
0, 3, 4
3, 4, 5
I need to create a query that groups by team_id and counts how many fails there are per result. If a result has more than one fail, then that overall result is a fail. thereby if the count of results in the above query is 3 (example: first result) then it should only be counted as one. The fail_group can be ignored for now as I believe that the same solution for fail_all will work for fail_group.
The result I hope for is:
team_id, amount_of_fails, amount_of_fails_per_group
1, 2, 2
2, 1, 2
I hope someone might be able to help me create the query that I need? I'm not even sure how to start.
Let me know if there is anything that I can do to adjust the query as I know it's not very well asked?
Thanks!
If you want that output. Maybe something like this:
SELECT
r.team_id,
SUM(IF(a.fail_all = 1,1,0)) AS amount_fail_all,
SUM(IF(a.fail_group = 1,1,0)) AS amount_fail_group
FROM answers AS a
JOIN results AS r on r.id=a.result_id
GROUP BY r.team_id
This will get you this output:
team_id amount_fail_all amount_fail_group
1 2 2
2 1 2

MySQL - How to query items by tags, order by matched tag count

My schema looks something like this:
items ( id, title, blah )
tags (id, name )
item_tags ( item_id, tag_id )
I want to list all items, where the item's tags are "in" an array of selected tags, and then order by the number of tags that match the selection (e.g. [1, 2, 3])
What I have so far is:
SELECT *, COUNT(item_tags.tag_id) AS tag_count
FROM items
JOIN item_tags
ON item_tags.item_id = items.id
WHERE item_tags.tag_id IN (1, 2, 3)
GROUP BY items.id
ORDER BY tag_count DESC
This works well, except the tag_count just gets the total number of tags for the item selected, i want it be the number of tags selected that are contained in (1, 2, 3).
An item with tags (1, 2, 3) should come before an item with tags (1, 5, 6, 7).
I am using Kohana 3's ORM if there is a solution that way.
Simply change your SELECT to:
SELECT *, COUNT(*) AS tag_count
.....
I think what you really want is a GROUP_CONCAT( tag_id ) (maybe in addition to your count). The group concat will concatinate your IDs such as you've shown... 1, 2, 3 and 1, 5, 6, 7. If you use THAT column as your order by, you should be good.
Now, that said, you might have to force some formatting of the concatination process to handle things like 1, 10, 100 coming before 1, 2, 3. As such, if formatting the concatinated ID strings to say... 2 or 3 positions, you would get
001, 002, 003
vs
001, 005, 006, 007
vs
001, 010, 100
HTH

SQL - select first in value set by priority?

I'm fairly inexperienced in SQL and this seems like it must be an easy task, but I'm not sure how to go about it.
Basically I want to select a single row from table A where field "someField" is in a pre-determined set "someSet", but I want it to look for each value in the set individually. For example, let's say "someSet" contains 5, 6, 9, 3. I would use a query similar to this:
SELECT * FROM A WHERE someField IN (5, 6, 9, 3) LIMIT 1
However, I want it to look for 5 first, then 6, then 9, then finally 3 if no rows have been found yet. Written as separate queries it'd look like this:
SELECT * FROM A WHERE someField = 5 LIMIT 1
(if no results returned)
SELECT * FROM A WHERE someField = 6 LIMIT 1
(if no results returned)
SELECT * FROM A WHERE someField = 9 LIMIT 1
(if no results returned)
SELECT * FROM A WHERE someField = 3 LIMIT 1
Obviously using 4 queries (theoretically infinite queries) isn't very elegant, is there a way to make this into a single query?
You can do
SELECT * FROM A WHERE someField IN (5, 6, 9, 3)
ORDER BY FIELD( someField, 5, 6, 9, 3)
LIMIT 1