mysql sorting data in two levels possible? - mysql

Iam trying to analyze some date from a mysql table.
The data is a representation of incomming calls, each line represents one call
category purpose
cars question
bikes question
cars question
cars complaints
scooters question
bikes complaints
now for the plotting I need the data to look like this
category cat_count question complaints
cars 3 2 1
bikes 2 1 1
scooters 1 1
I figured out that I can sort and count by one field by using something like this
SELECT category, count(*) FROM stat GROUP BY category ORDER BY count(*) desc;
which will give me
category count
cars 3
bikes 2
scooters 1
but how can I add the purpose counts to that output?
I would usually write a php or bash script, but if its possible to do it in mysql I would rather do it like that instead of having a 3 loop script noone will understand in 1 year :-))
Thanks in advance for any hint (even if the hint is "impossible")

You can do this way:
SELECT category, count(*) as cat_count,
SUM(CASE WHEN purpose='question' THEN 1 ELSE 0 END) as question,
SUM(CASE WHEN purpose='complaints' THEN 1 ELSE 0 END) as complaints
FROM stat
GROUP BY category
ORDER BY count(*) desc;
Result:
CATEGORY CAT_COUNT QUESTION COMPLAINTS
cars 3 2 1
bikes 2 1 1
scooters 1 1 0
See result in SQL Fiddle.

Related

MySQL count and case with one to many relationship

My first question here.
I got 2 tables with one to many relationship:
policies
id
issue_date
user_id
insurance_type
1
1-2-2021
100
apartment
2
1-2-2021
200
car
policy_details
id
policy_id
type
1
1
type A
1
1
type A
2
1
type B
3
1
type C
1 policy record can have many policy_details records.
I need to count the policies rows with some case,
and I need to join the policy_details as well because I count them also.
Example to simple query:
SELECT
user_id,
COUNT(CASE WHEN `insurance_type` = 'apartment' THEN 1 ELSE NULL END) as totalApartmentType,
COUNT(CASE WHEN policy_details.type = 'typeA' THEN 1 ELSE NULL END) as totalTypeA
FROM `policies`
JOIN `policy_details` ON policy_details.policy_id = policies.id
AND MONTH(`issue_date`) = 2
GROUP BY (`user_id`)
The problem here is that if 1 policy connected to 2 policy_details records for example,
the count will be 2 and it should be 1, cause I need to count the policy record, not the policy_details joined records.
And if policy_details has 5 records connected to policy, the count will be 5. (should be 1).
The result I need for the query above:
user_id
totalApartmentType
totalTypeA
100
1
2
Can it be done guys?
You can use COUNT(DISTINCT) making sure you generate the id instead of 1 in case the condition is fulfilled:
COUNT(DISTINCT CASE WHEN insurance_type = 'apartment'
THEN policies.id
ELSE NULL
END) AS totalApartmentType,

SQL: Group By specific values and add up their count column

I need to group a chunk of values into it's own, and get a total count for each group.
name|count
alex 3
amy 6
james 3
john 33
joe 12
zane 1
pane 5
I have a sql query like this but I think it is incorrect. basically I need to add the total count for each group, and right now it just counts the number of rows.
select Name,
count(case when Text like 'alex' or Text like 'amy' then 1 end) as group1,
count(case when Text like 'j%' then 1 end) as group2,
count(case when Text like 'zane' or Text like 'pane' then 1 end) as group3,
from MyTable
group by Name
The important criteria is that I need to group people by their names, this grouping is not trivial and needs to be done specifically by individual values.

MySQL order by points from 2nd table

So I have MySQL 3 tables, items (which in this case are lodging properties and the data is simplified below), amenities that the properties might offer, and amenities_index which is a list of item ids and amenity ids for each amenity offered. The end user can select any number of amenities they want and I want to return the results in order of the number of amenities that match what they are looking for. So, if they search for 3 different amenities, I want the items listed that offer all 3, then those that offer 2, 1 and finally the rest of the items. I have a query that I think is working for getting the results in the correct order, but I was hoping that I could also return a point value based on the matches, and that's where I'm running into trouble. My SQL skills are a bit lacking when it comes to more complex queries.
Here is an example query I have that returns the results in the correct order:
SELECT * FROM items
ORDER BY
(
SELECT count(*) AS points
FROM `amenities_index`
WHERE
(amenity_id = 1 || amenity_id = 2)
AND amenities_index.item_id = items.id
) DESC
And here is what the tables are structured like. Any help is appreciated.
items table
id name
1 location 1
2 location 2
3 location 3
4 location 4
amenities table
id name
1 fireplace
2 television
3 handicapped accessible
4 kitchenette
5 phone
amenities_index
item_id amenity_id
1 2
1 3
1 5
2 1
2 2
2 6
3 2
3 3
3 4
3 5
You want to move your expression into the select clause:
SELECT i.*,
(SELECT count(*) AS points
FROM `amenities_index` ai
WHERE amenity_id in (1, 2) AND
ai.item_id = i.id
) as points
FROM items i
ORDER BY points desc;
You can also do this as a join query with aggregation:
SELECT i.*, ai.points
FROM items i join
(select ai.item_id, count(*) as points
from amenities_index ai
where amenity_id in (1, 2)
) ai
on ai.item_id = i.id
ORDER BY ai.points desc;
In most databases, I would prefer this version over the first one. However, MySQL would allow the first in a view but not the second, so it has some strange limitations under some circumstances.

Select with a where clause and without it in the same query

I'm trying to find a way to sum amounts that match a specific term, and also amounts that don't match it. For example, if my table looks like this
user amount description
1 34 bike
1 78 toys
2 3 fuel
2 12 bike
I'm trying to get a table that will look like this in the end:
user amount spent on bike amount spent total
1 34 112
2 12 15
I'm using mysql
You can use a CASE statement within a SUM grouping:
SELECT user,
SUM(CASE WHEN description = 'bike' THEN amount ELSE 0 END) bike_amount,
SUM(amount) total_amount
FROM mytable
GROUP BY user

Effective way to count all categories total number of one table in one query in MySQL?

E.g: data table with these records:
data_id data category
1 hello 1
2 world 1
3 john 1
4 kevien 2
5 apple 2
6 bannana 3
7 desk 4
And how can I count the categories total number in one query in MySQL!?
[UPDATE]
How about count total number in special categories.Such as only category 1 and 3??
Thank you very much!!
In response to the question in the comment, include the where clause to restrict it:
SELECT category, count(*) from table
where category in (1, 3)
group by category
select category, count(*)
from theTable
group by category