Adding attributes to an row count - mysql

I have the following table:
OrderHasItem
OrderTable_idOrder
Item_idItem
quantity
SELECT Item_idItem, COUNT(Item_idItem)+quantity
FROM OrderHasItem
GROUP BY Item_idItem
I want to count how many of each item, but also take into account the quantity of each entry.
The problem is when I tried it with this data I got really strange results:
Data:
OrderTable_idOrder, Item_idItem, quantity
1, 1, 1
2, 1, 2
34, 4, 2
43, 4, 1
77, 2, 1
Result:
Item_idItem, COUNT(Item_idItem)+quantity
1, 3
2, 2
4, 4
I don't really understand how it got what it gave me so I'm not quite sure how to proceed. Thank you for the help.
Here is the target Data:
Item_idItem, quantity
1, 3
4, 3
2, 1

SELECT Item_idItem, COUNT(Item_idItem), COUNT(Item_idItem)+SUM(quantity)
FROM OrderHasItem
GROUP BY Item_idItem
I think it should work, if sum of quantity and number of items is required.
Or
SELECT Item_idItem, SUM(quantity)
FROM OrderHasItem
GROUP BY Item_idItem
if only sum of quantity is required.

Because quantity is not part of the GROUP BY clause it can not be selected reliably. So MySQL is returning more or less arbitrary data.
Zohaib has a query that you should use. I wanted to provide the explanation.

Related

How to use "ORDER BY FIELD" to sort the result of a SQL

If there is a data shown as below;
id cnt_stamp
1 999
2 3
3 9
4 3
5 1000
6 30
If an input is (4, 1, 2, 3) in this order, I would like to get only (3, 999, 3, 9).
To achieve this, I created a SQL
SELECT `cnt_stamp`
FROM `stm_events`
ORDER BY FIELD(`id`, 4, 1, 2, 3);
But it returns (1000, 30, 3, 999, 3, 9) instead. How should I fix my SQL to achieve my goal? Thank you for taking your time.
FIELD will assign NULL to any non matching id, and nulls sort first by default in MySQL. If you don't want to see non matching items at all you may just add a WHERE clause:
SELECT cnt_stamp
FROM stm_events
WHERE id IN (1, 2, 3, 4)
ORDER BY FIELD(id, 4, 1, 2, 3);
If you want to see all your data, with non matching id values at the end, then reverse the order of the field list and sort descending:
SELECT cnt_stamp
FROM stm_events
ORDER BY FIELD(id, 3, 2, 1, 4) DESC;
Demo
Use COALESCE function :
SELECT `cnt_stamp`
FROM `stm_events`
ORDER BY COALESCE(`id`,FIELD(`id`,4,1,2,3));
SQL Fiddle Demo

SQL: Query formatting

I have a SQL query with three columns. The first is Year (categorical), the second is Site (categorical) and the last is temperature (float). The rows as unique combinations of Year X Site. For example:
Current query result
Year, Site, Temp
1, 1, x11
1, 2, x12
1, 3, x13
2, 1, x21
2, 2, x22
2, 3, x23
3, 1, x31
3, 2, x32
3, 3, x33
I would like to have each site as a different column, while keeping years as rows. For example:
Desired query result
Year, TSite1, TSite2, TSite3
1, x11, x12, x13
2, x21, x22, x23
3, x31, x23, x33
Any ideas on how to do a query that results in this format? I would not mind using a temporary table or a view to store the information.
Thanks in advance.
SELECT Year,MIN(CASE WHEN Site=1 THEN Temp ELSE 0 END) as Tsite1,
MIN(CASE WHEN Site=2 THEN Temp ELSE 0 END) as Tsite2,
MIN(CASE WHEN Site=3 THEN Temp ELSE 0 END) as Tsite3 FROM table GROUP BY Year
A pivot query is one approach (as mentioned in the comments) If you just want a comma-delimited list of sites, then you can do that with group_concat().
select year, group_concat(temp separator ', ' order by site) as temps
from t
group by year;
I realize this may not be exactly what you want -- you lose the type information for temp by converting it to a string for example. But then again, it may be what you need if you just want to see the temps or export them to another tool.

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