I have table that looks like the following:
`units`
+----+------+-------+---------------+-------+
| id | tech | jobID | city | units |
+----+------+-------+---------------+-------+
| 1 | 1234 | 8535 | San Jose | 3 |
| 2 | 1234 | 8253 | San Francisco | 4 |
| 3 | 1234 | 2457 | San Francisco | 5 |
| 4 | 1234 | 8351 | Mountain View | 8 |
+----+------+-------+---------------+-------+
and a view that uses this data to do some computations:
`total`
+----+--------+------+-------+
| id | name | tech | total |
+----+--------+------+-------+
| 1 | Dan | 1234 | 12 |
| 2 | Dan SF | 1234 | 12 |
+----+--------+------+-------+ ...
My problem is that I am trying to sum up the amount of units Dan completed in San Francisco and the amount of units he did elsewhere (need to specifically track how many units were completed in SF). However, I'm unsure of how to do this within my select query and if you look at my current total table, you'll see that both total values are simply summing all of the units regardless of city.
I want to get the following:
`total`
+----+--------+------+-------+
| id | name | tech | total |
+----+--------+------+-------+
| 1 | Dan | 1234 | 11 |
| 2 | Dan SF | 1234 | 9 |
+----+--------+------+-------+ ...
I need help writing my SELECT because I'm unsure of how to use CASE to get the desired result. I've tried the following:
SELECT otherTable.name AS name, units.tech AS tech,
(CASE WHEN City = 'SAN FRANCISCO' THEN SUM(units)
ELSE SUM(units)
) AS total
FROM units, otherTable
GROUP BY name
but clearly this won't work since I'm not differentiating between cities in the two aggregates.
Any help is greatly appreciated.
EDIT: The SELECT query for my current view (with join info) is as follows:
SELECT otherTable.name, units.tech, SUM(units.units)
FROM units
LEFT JOIN otherTable ON otherTable.tech = units.tech
GROUP BY name
As for otherTable, it simply associates each tech ID with a name:
`otherTable`
+----+--------+------+-----------+
| id | name | tech | otherInfo |
+----+--------+------+-----------+
| 1 | Dan | 1234 | ...... |
+----+--------+------+-----------+
First off, it appears that your base query is wrong. There isn't nothing about the join between units and otherTable, but I don't know enough to put it in.
It seems strange to me that you would want it broken out into rows instead of columns, but you could do the following:
SELECT otherTable.name AS name, units.tech AS tech,
SUM(units) AS total
FROM units, otherTable
-- not sure if this section should exclude 'SAN FRANCISO' or not
GROUP BY name
UNION ALL
SELECT otherTable.name || ' SF' AS name, units.tech AS tech,
SUM(units) AS total
FROM units, otherTable
WHERE City = 'SAN FRANCISCO'
GROUP BY name
This would give you
+--------+------+-------+
| name | tech | total |
+--------+------+-------+
| Dan | 1234 | 11 |
| Dan SF | 1234 | 9 |
+--------+------+-------+
Or if you want separate columns, you could do this
SELECT otherTable.name AS name, units.tech AS tech,
SUM(units) AS total,
SUM(CASE WHEN City = 'SAN FRANCISCO' THEN units
ELSE 0
) AS sf_total
FROM units, otherTable
GROUP BY name
This would give you
+--------+------+-------+----------+
| name | tech | total | sf_total |
+--------+------+-------+----------+
| Dan | 1234 | 11 | 9 |
+--------+------+-------+----------+
Related
I have two tables:
Table students and table of school work delivered
Students table
+--------------------------+---------------------------------+
| id | name |
+--------------------------+---------------------------------+
| 1 | ADAM |
| 2 | BRIGITTE |
| 3 | ANNE |
+--------------------------+---------------------------------+
table student works
+---------------+-------------------------+------------------+
| id_works | works | id_student |
+---------------+-------------------------+------------------+
| 1 | airplane wing | 1 |
| 2 | volcano | 2 |
| 3 | law of gravity | 1 |
| 4 | airplane wing | 3 |
| 5 | law of gravity | 1 |
+-----------------------------------------+------------------+
How do I make a SELECT for work that returns the entire list of students, indicating that the work is delivered? (IMPORTANT: list of all students)
Example
LIST FOR WORK **airplane wing**
+--------------------------+---------------------------------+
| ADAM | X |
| BRIGITTE | |
| ANNE | X |
+--------------------------+--------------------- -----------+
I have tried it with LEF JOIN and IF, but it is not the list of all the students without repeating them.
SELECT
s.name ,
w.work,
w.resid_id,
if(w.work = 'airplane wing', 'X', '') as mark
FROM students s
LEFT JOIN works w
ON s.id = w.id_student
ORDER BY s.name ASC
This will give you a list of all students
And fields id_works and works will be null for those who didn't complete the work
SELECT s.name, w.id_works, w.works
FROM students s
LEFT JOIN works w
ON (w.id_student = s.id AND w.works = 'airplane wing')
ORDER BY s.name ASC
I have 2 tables like this.
Table : Family Members
----------------------------------
|Address | Name |
----------------------------------
|North Jakarta City | Andra |
|North Jakarta City | Halim |
|South Jakarta City | Irma |
|Thousand Island Village | Dian |
----------------------------------
Table : Member Details
---------------
| Name | Age |
---------------
| Andra | 1 |
| Halim | 50 |
| Irma | 20 |
| Dian | 4 |
---------------
What is the correct query if I want to count members between the ages 0 and 4 who live in a 'city'? I've tried using this query but the result is incorrect. The correct result should be 1 since only Andra who lives in a city and between the ages 0 and 4. Please help me.
SELECT COUNT(family_members.name) AS total FROM family_members, member_details
WHERE family_members.address LIKE '%City%' AND member_details.age BETWEEN 0 AND 4
You need a join
SELECT COUNT(fm.name) AS total
FROM family_members fm
Join member_details md on md.Name = fm.Name
WHERE fm.address LIKE '%City%' AND md.age BETWEEN 0 AND 4
with you syntax, you may add this in the where clause (because your query will generate a cartesian product).
BUT : you should really use the JOIN syntax
AND family_members.Name = member_details.Name
EDIT
By the way, I would strongly suggest to use surrogate keys in your tables (a name is not really something unique)
You should consider redesigning your database like:
----------------------------------
| user_id | Name | Age | city_id |
----------------------------------
| 1 | Andra | 1 | 1 |
| 2 | Halim | 50 | 1 |
| 3 | Irma | 20 | 1 |
| 4 | Dian | 4 | 2 |
----------------------------------
------------------------------------
|city_name | city_id |
------------------------------------
|North Jakarta City | 1 |
|Thousand Island Village | 2 |
------------------------------------
SELECT COUNT(*) AS total
FROM family_member
JOIN city on family_member.city_id = city.city_id
WHERE city.city_name= 'City' AND family_member.age BETWEEN 0 AND 4;
Also you should add indexes.
Good afternoon everyone,
I wonder if I can get help with this example in a database.
I have listings delivered as:
------------------------------------
| Id | name | price |
-------------------------------
| 1 | Hawaii | 20.58 |
| 2 | Hawaii VIP | 45.58 |
| 3 | Aruba | 13.58 |
| 4 | Aruba VIP | 34.58 |
| 5 | Japon | 14.58 |
| 6 | Japon VIP | 34.58 |
| 7 | Alemania | 14.58 |
| 8 | Alemania VIP | 14.58 |
But I need them to be shown as follows:
-----------------------------------------------------
| Id | name | price basic | price vip
-----------------------------------------------------
| 1 | Hawaii | 20.58 | 45.34 |
| 5 | Japon | 14.58 | 34.58 |
etc etc etc
What I need are the two prices of the same country in a different column in the same query.
As I can catch the "VIP" based on this field and put it in a column with its value
It would be better to store IS_VIP as a separate column in the first table instead of adding it to the name, but since it's not a perfect world, you could solve it like this until then. :)
SELECT
t.Id,
t.name,
t.price as "price basic",
v.price as "price VIP"
FROM YourTable t
JOIN YourTable v ON v.name = CONCAT(t.name, ' VIP')
Sql Fiddle Example
For example, I have fruit come from different country and have different brand(note that the country and brand is independence).
+-------+-------+---------+-------+
| name | stock | Country | brand |
+-------+-------+---------+-------+
| apple | 40 | USA | Sun |
| apple | 38 | UK | Sun |
| apple | 33 | CN | Green |
| apple | 29 | UK | Air |
| apple | 15 | USA | Green |
+-------+-------+---------+-------+
Normally if we use this command
SELECT name, Country, sum(stock)
FROM table
GROUP BY Country
It will give the following result
+-------+---------+------------+
| name | Country | sum(stock) |
+-------+---------+------------+
| apple | CN | 33 |
| apple | UK | 67 |
| apple | USA | 55 |
+-------+---------+------------+
But what I want is this....
+-------+----------+-------+
| name | category | stock |
+-------+----------+-------+
| apple | USA | 55 |
| apple | UK | 67 |
| apple | CN | 33 |
| apple | Sun | 78 |
| apple | Green | 48 |
| apple | Air | 29 |
+-------+----------+-------+
For some result, the command must be one step command, which means only for one command it should able to directly output the above result just one click.
I would suggest doing this with a subquery:
select name, category, sum(stock)
from (select name, brand as category, stock, 1 as ordering
from table
union all
select name, country, stock, 0 ordering
from table
) t
group by name, category, ordering
order by ordering, name;
Note the use of the ordering column to ensure that the results appear in the same order as in your desired results. Also, this will keep two rows in cases where the brand and country have the same name. You can remove the ordering from the group by if you want them combined.
try reading into unions or left join
i think you need to make
SELECT name, Country as category, sum(stock)
into #temptable1 FROM table
GROUP BY Country
and
SELECT name, brand as category, sum(stock)
into #temptable2 FROM table
GROUP BY brand
then join the two temp tables together
this can be done using stored procedures
or simply union directly without making temp tables
SELECT name, Country as category, sum(stock)
into #temptable1 FROM table
GROUP BY Country
UNION
SELECT name, brand as category, sum(stock)
into #temptable2 FROM table
GROUP BY brand
I am actually facing an issue with MySQL, I need to have a similar behavior of the GROUP BY but without grouping.
Here is an example for just one table named 'resident' with 2 columns: 'name', 'city'.
If i want to count the number residents for each city, i just need to do this :
SELECT resident.city, count(resident.name) as 'Nb residents'
FROM resident
GROUP BY resident.city
So the result would be like :
| city | Nb residents |
| NY | 3 |
| HK | 1 |
| Rome | 2 |
...
But i am looking for a way to display my result like that :
| name | city | Nb residents |
| Name1 | NY | 3 |
| Name2 | NY | 3 |
| Name3 | NY | 3 |
| Name4 | HK | 1 |
| Name5 | Rome | 2 |
| Name6 | Rome | 2 |
Is it possible to do that ?
Thanks for your help.
SELECT resident.name, resident.city, (select count(a.name) from resident a where a.city = resident.city) as 'Nb residents'
FROM resident
You could to this with the following query:
SELECT t1.`name`, t2.`city`, t3.`Nb residents`
FROM resident t1
JOIN ( SELECT resident.city, count(resident.name) as 'Nb residents' FROM resident GROUP BY resident.city ) t2
ON t1.`city`= t2.`city`
This extracts the amount of residents per city in a subquery and then joins this with the names of the very table.