MySQL sum of distinct rows - php

I have a query performing INNER JOINs pulling in a relational cross reference table. So based on the query, I'm getting all (one to many) 'fruits' related to a basket. I need to sum the amount of fruits distinctly.
| Banana | 1 |
| Banana | 1 |
| Apple | 1 |
| Pear | 1 |
| Pear | 1 |
| Pear | 1 |
I want the result set to look like this...
| Banana | 2 |
| Apple | 1 |
| Pear | 3 |
I tried to SUM() fruit in the SELECT with a GROUP BY but the results were not correct (way off). I'm thinking HAVING might need to come into play... anyway, frustrated since this should be pretty easy.

If there are only 1's in the second column, try:
SELECT fruit, count(fruit)
FROM fruits_table
GROUP BY fruit

Not too difficult with a SUM() and GROUP BY:
select a.fruit, sum(a.num) as number
from fruits a
group by a.fruit;
SQLFiddle: http://sqlfiddle.com/#!2/3b53a/1

Try this code:
select fruit_name, sum(qte)
from fruit_table_name
group by fruit_name;

Related

Trying to join tables in MySQL

i'm new to MySQL and PHP. And i have some problems trying to get data values from two tables in one query using JOIN. What i want to do is query "user_builds" and SUM(amount) where the owner_id=1 AND type=1. The problems comes in now where i have to grab the build_type from another table called "builds".
I have tried to solve this as i mentioned with JOIN, but the closest i came was to get the amount of rows that was equal to how many rows user_id=1 had.
What i want is select the total SUM of "amount"(user_builds) where "type=1"(builds) and "owner_id=1"(user_builds).
I hope you understand what i try to do here, if not i will try to elaborate it more. And also sorry for not providing any of the querys i tried, but as none of them worked it feels irrelevant. Thank you for your time.
Edit:
+-------------------+
| user_builds |
+---------+---------+----------+-------+
| id |owner_id | build_id | amount|
+---------+---------+----------+-------+
| 1 | 1 | 1 | 5 |
| 2 | 2 | 2 | 15 |
| 3 | 2 | 3 | 15 |
| 4 | 1 | 4 | 5 |
| 5 | 1 | 5 | 5 |
| 6 | 1 | 6 | 10 |
+---------+---------+----------+-------+
+----------------------+
| build |
+---------+------------+-----------+--------+
| id | name |description| type |
+---------+------------+-----------+--------+
| 1 | House | desc | 1 |
| 2 | Kitchen | desc | 2 |
+---------+------------+-----------+--------+
I want to query "user_builds" and get the total of "amount" where owner_id=1 and type=1. (type is found in "build" table).
Try this code, I hope it works appropriately.
select sum(ub.amount)
from user_builds ub
left join build b
on ub.build_id = b.id
where b.type=1
and ub.owner_id = 1
select SUM(amount) from user_builds left join builds on build.type = user_builds.type where "owner_id=1"
try this query and replace my query field with your original fields
best of luck...

Mysql join query multiple values

I have a table called facility.
Structure looks as follows:
id | name
---------
1 | Hotel
2 | Hospital
3 | medical shop
I have an other table which is taking data from the above table and keeping multiple values in one column. View looks like below:
id | facilities
---------------
1 | Hospital~~medical shop~~Hotel
2 | Hospital~~Hotel
3 | medical shop~~Hotel
If I want to join these two tables how does the query look like?
I tried this, but it didn't work:
select overview.facilities as facility
from overview join facility on facility.id=overview.facilities;
you can do this with a bit of hackery
select o.facilities as facility
from overview o
join facility f on find_in_set(f.facilities, replace(o.facilities, '~~', ','));
I would highly recommend you change the way you are storing data. currently it is considered un normalized and that quickly becomes a monster to deal with
you should change your table structure to look something more like this
+----------+--------------+
| facility |
+----------+--------------+
| id | name |
+----------+--------------+
| 1 | Hotel |
| 2 | Hospital |
| 3 | medical shop |
+----------+--------------+
+-----------+-------------+
| overview |
+-----------+-------------+
| id | facility_id |
+-----------+-------------+
| 1 | 2 |
| 2 | 3 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 3 |
| 7 | 1 |
+-----------+-------------+
Code Explanation:
basically you are wanting to find the matching facilities in the overview. one handy function MySQL has is FIND_IN_SET() that allows you to find an item in a comma separated string aka find_in_set(25, '11,23,25,26) would return true and that matching row would be returned... you are separating your facilities with the delimiter ~~ which wont work with find_in_set... so I used REPLACE() to change the ~~ to a comma and then used that in the JOIN condition. you can go from here in multiple ways.. for instance lets say you want the facility id's for the overview.. you just add in the select GROUP_CONCAT(f.id) and you have all of the id's... note if you do that you need to add a GROUP BY at the end of your query to tell it how you want the results grouped

count number of rows that have the same combination of two colums

Hi I have 2 table Offense table and User_jobs table
offense table:
crime_id |crime_type |casenumber|
---------+-----------+----------+
1 | 3 |1 |
2 | 3 |1 |
1 | 3 |2 |
12 | AA |2 |
user_jobs table:
casenumber |disposal_status |
-----------+----------------+
1 | yes |
1 | yes |
2 | no |
2 | no |
what i want is to count the number of rows with the same combination say crime_id=1 and crime_type= 3 but these must have a disposal status of yes in the user_jobs table.
i want to do this in mysql. pliz help
sorry but i am new to mysql. i now want to display the real names of those id not the id themselves.
the tables with these IDs are crime_category and Crime_type Crime_catgory
table:
category |crime_id |
-----------+----------------+
theft | 1 |
murder | 2 |
rape | 3 | 2 |
no |
Crime_type table:
Crime_type |id |
---------------+----------------+
administrative | yes |
criminal | yes |
You can do this with a simple inner join and an aggregate function:
select
o.crime_id,
o.crime_type,
count(*)
from
offence o
join user_jobs uj
on o.casenumber=uj.casenumber
where
uj.disposal_status='Yes'
group by
o.crime_id,
o.crime_type
This will pick up distinct combinations of the first two columns joined as they should tot he jobs table and only where the disposal_status is equal to 'Yes'
Edit: You would probably do really well to have a read of this Q&A that I put together for exactly this sort of situation - where I give you the code for it, but would like to explain this is a lot more detail. The Q&A explains why this type of thing (and many many others) work and how they do so:
How can an SQL query return data from multiple tables
Edit 2:
select
o.crime_id,
o.crime_type,
ct.category,
count(*)
from
offence o
join user_jobs uj
on o.casenumber=uj.casenumber
join crime_type ct
on o.crime_type=ct.crime_id
where
uj.disposal_status='Yes'
group by
o.crime_id,
o.crime_type,
ct.category,

Run While Loop Through All Distinct Values of A Column

This is an example MYSQL result
+----+---+
| A | B |
+----+---+
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 5 |
+----+---+
I would like to run through every distinct in Column A and do something utilizing the values in Column B.
Let's say A has userids and B has foods. I would like to grab all the foods that user 1 likes and then shoot an email to 1, then grab all the foods that user 2 likes and email to her, and so forth. Would appreciate any suggestions.
If you want comma separated values, you can use GROUP_CONCAT
SELECT A, GROUP_CONCAT(DISTINCT B) foodList
FROM tableName
GROUP BY A
SQLFiddle Demo
Other Link
GROUP BY clause

Does ORDER BY apply before or after DISTINCT?

In a MySQL query, when using the DISTINCT option, does ORDER BY apply after the duplicates are removed? If not, is there any way to make it do so? I think it's causing some issues with my code.
EDIT:
Here's some more information about what's causing my problem. I understand that, at first glance, this order would not be important, since I am dealing with duplicate rows. However, this is not entirely the case, since I am using an INNER JOIN to sort the rows.
Say I have a table of forum threads, containing this data:
+----+--------+-------------+
| id | userid | title |
+----+--------+-------------+
| 1 | 1 | Information |
| 2 | 1 | FAQ |
| 3 | 2 | Support |
+----+--------+-------------+
I also have a set of posts in another table like this:
+----+----------+--------+---------+
| id | threadid | userid | content |
+----+----------+--------+---------+
| 1 | 1 | 1 | Lorem |
| 2 | 1 | 2 | Ipsum |
| 3 | 2 | 2 | Test |
| 4 | 3 | 1 | Foo |
| 5 | 2 | 3 | Bar |
| 6 | 3 | 5 | Bob |
| 7 | 1 | 2 | Joe |
+----+----------+--------+---------+
I am using the following MySQL query to get all threads, then sort them based on the latest post (assuming that posts with higher ids are more recent:
SELECT t.*
FROM Threads t
INNER JOIN Posts p ON t.id = p.threadid
ORDER BY p.id DESC
This works, and generates something like this:
+----+--------+-------------+
| id | userid | title |
+----+--------+-------------+
| 1 | 1 | Information |
| 3 | 2 | Support |
| 2 | 1 | FAQ |
| 3 | 2 | Support |
| 2 | 1 | FAQ |
| 1 | 1 | Information |
| 1 | 1 | Information |
+----+--------+-------------+
However, as you can see, the information is correct, but there are duplicate rows. I'd like to remove such duplicates, so I used SELECT DISTINCT instead. However, this yielded the following:
+----+--------+-------------+
| id | userid | title |
+----+--------+-------------+
| 3 | 2 | Support |
| 2 | 1 | FAQ |
| 1 | 1 | Information |
+----+--------+-------------+
This is obviously wrong, since the "Information" thread should be on top. It would seem that using DISTINCT causes the duplicates to be removed from the top to the bottom, so only the final rows are left. This causes some issues in the sorting.
Is this the case, or am I analyzing things incorrectly?
Two things to understand:
Generally speaking, resultsets are unordered unless you specify an ORDER BY clause; to the extent that you specify a non-strict order (i.e. ORDER BY over non-unique columns), the order in which records that are equal under that ordering appear within the resultset is undefined.
I suspect you may be specifying such a non-strict order, which is the root of your problems: ensure that your ordering is strict by specifying ORDER BY over a set of columns that is sufficient to uniquely identify each record for which you care about its final position in the resultset.
DISTINCT may use GROUP BY, which causes the results to be ordered by the grouped columns; that is, SELECT DISTINCT a, b, c FROM t will produce a resultset that appears as though ORDER BY a, b, c has been applied. Again, specifying a sufficiently strict order to meet your needs will override this effect.
Following your update, bearing in mind my point #2 above, it is clear that the effect of grouping the results to achieve DISTINCT makes it impossible to then order by the non-grouped column p.id; instead, you want:
SELECT t.*
FROM Threads t INNER JOIN Posts p ON t.id = p.threadid
GROUP BY t.id
ORDER BY MAX(p.id) DESC
DISTINCT informs MySQL how to build a rowset for you, ORDER BY gives a hint how this rowset should by presented. So the answer is: DISTINCT first, ORDER BY last.
The order in which DISTINCT and ORDER BY are applied, in most cases, will not affect the final output.
However, if you also use GROUP BY, this will affect the final output. In this case, the ORDER BY is performed after the GROUP BY, which will return unexpected results (assuming you expect the sort to be performed before the grouping).

Categories