Showing rows as columns in MySQL - mysql

I have a networks table and a groups table and they are linked by each group being connected to a network.
Each group have a type and some of these groups are special type of groups.
I'm trying to run query that will display each group that is a a special type to be displayed as a column showing how many people are in that group type.
Is that something that is possible? Having each group type being displayed as a column header.
Data:
Networks
id | name
1 | networka
2 | networkb
groups
id | name | type | network
1 | groupa | 1 | 1
2 | groupb | 2 | 2
3 | groupc | 3 | 1
type
id | name | special
1 | speciala | 0
2 | specialb | 1
I currently running:
SELECT Name FROM (
SELECT groups.Name FROM groups INNER JOIN group_types on groups.Type = group_types.Id WHERE group_types.SpecialType = 1 Group by groups.Type
) as s
which returns the list of groups with special type. But if I want to get more information such as the number of members in that group assuming I have a group_members table that links back to the groups table or the numbers of groups with that type.
I currently get two a row:
name
specialb
but I actually want to return back
specialb
(sub query to get more values for that special group)

If I'm understanding what you want correctly, write this:
select g.name, t.name, count(*)
from groups as g left join group_members as gm on gm.group=g.id left join types as t on t.id=g.type
group by g.name, t.name
then copy and paste into Excel using paste special > transpose.

Related

Joinin multiple tables with double group by,double count

I am trying to expand my Select to handle displaying number of files associated with Unique "NR_REKLAMACJI". I Got table 'rtransportowa' where i keep all details, 'klienci' where i get Name and Surname and now im trying to join table 'pliki' or 'files' as well, to keep track on how many files there are for corresponding 'NR_REKLAMACJI'.
Tried adding Count(files.FileName) on select and then Inner joining it and using group by NR_REKLAMACJI, files.NR_REK
SELECT
`NR_REKLAMACJI`,
COUNT(NR_REKLAMACJI) AS 'ilosc reklamowanego towaru',
CONCAT(klienci.IMIE, ' ', klienci.NAZWISKO) AS 'Klient',
CONCAT(users.IMIE, ' ', users.NAZWISKO) AS 'Osoba zajmująca się',
DOK_FV,
klienci.NAZWA_FIRMY,
DATA
FROM
`rtransportowa`
INNER JOIN klienci ON ID_R = klienci.ID_KLIENTA
INNER JOIN users ON ID_U = users.ID_USER
group by
NR_REKLAMACJI
My goal is to group table 'rtransportowa' to show unique 'NR_REKLAMACJI" and count number of "NR_REKLAMACJI" from rtransportowa and files,
I got TABLE1 with not unique field NAME, TABLE 2 having also field NAME, and i want to group it by showing all things from TABLE1 + Count(NAME), grouping it by field NAME, and for this add Count of (TABLE2.NAME) also grouped by the TABLE1.NAME
+------+-------------+--------------------+
| Name | Count(Name) | Count(TABLE2.Name) |
+------+-------------+--------------------+
| aaa | 2 | 3 |
| bbb | 3 | 0 |
| ccc | 1 | 45 |
+------+-------------+--------------------+

MySQL selective GROUP BY, using the maximal value

I have the following (simplified) three tables:
user_reservations:
id | user_id |
1 | 3 |
1 | 3 |
user_kar:
id | user_id | szak_id |
1 | 3 | 1 |
2 | 3 | 2 |
szak:
id | name |
1 | A |
2 | B |
Now I would like to count the reservations of the user by the 'szak' name, but I want to have every user counted only for one szak. In this case, user_id has 2 'szak', and if I write a query something like:
SELECT sz.name, COUNT(*) FROM user_reservations r
LEFT JOIN user_kar k ON k.user_id = r.user_id
LEFT JOIN szak s ON r.szak_id = r.id
It will return two rows:
A | 2 |
B | 2 |
However I want to every reservation counted to only one szak (lets say the highest id only). I tried MAX(k.id) with HAVING, but seems uneffective.
I would like to know if there is a supported method for that in MySQL, or should I first pick all the user ID-s on the backend site first, check their maximum kar.user_id, and then count only with those, removing them from the id list, when the given szak is counted, and then build the data back together on the backend side?
Thanks for the help - I was googling around for like 2 hours, but so far, I found no solution, so maybe you could help me.
Something like this?
SELECT sz.name,
Count(*)
FROM (SELECT r.user_id,
Ifnull(Max(k.szak_id), -1) AS max_szak_id
FROM user_reservations r
LEFT OUTER JOIN user_kar k
ON k.user_id = r.user_id
GROUP BY r.user_id) t
LEFT OUTER JOIN szak sz
ON sz.id = t.max_szak_id
GROUP BY sz.name;

MySQL SELECT Multiple DISTINCT COUNT

Here is what I'm trying to do. I have a table with user assessments which may contain duplicate rows. I'm looking to only get DISTINCT values for each user.
In the example of the table below. If only user_id 1 and 50 belongs to the specific location, then only the unique video_id's for each user should be returned as the COUNT. User 1 passed video 1, 2, and 1. So that should only be 2 records, and user 50 passed video 2. So the total for this location would be 3. I think I need to have two DISTINCT's in the query, but am not sure how to do this.
+-----+----------+----------+
| id | video_id | user_id |
+-----+----------+----------+
| 1 | 1 | 1 |
| 2 | 2 | 50 |
| 3 | 1 | 115 |
| 4 | 2 | 25 |
| 5 | 2 | 1 |
| 6 | 6 | 98 |
| 7 | 1 | 1 |
+-----+----------+----------+
This is what my current query looks like.
$stmt2 = $dbConn->prepare("SELECT COUNT(DISTINCT user_assessment.id)
FROM user_assessment
LEFT JOIN user ON user_assessment.user_id = user.id
WHERE user.location = '$location'");
$stmt2->execute();
$stmt2->bind_result($video_count);
$stmt2->fetch();
$stmt2->close();
So my query returns all of the count for that specific location, but it doesn't omit the non-unique results from each specific user.
Hope this makes sense, thanks for the help.
SELECT COUNT(DISTINCT ua.video_id, ua.user_id)
FROM user_assessment ua
INNER JOIN user ON ua.user_id = user.id
WHERE user.location = '$location'
You can write a lot of things inside a COUNT so don't hesitate to put what you exactly want in it. This will give the number of different couple (video_id, user_id), which is what you wanted if I understood correctly.
The query below joins a sub-query that fetches the distinct videos per user. Then, the main query does a sum on those numbers to get the total of videos for the location.
SELECT
SUM(video_count)
FROM
user u
INNER JOIN
( SELECT
ua.user_id,
COUNT(DISTINCT video_id) as video_count
FROM
user_assessment ua
GROUP BY
ua.user_id) uav on uav.user_id = u.user_id
WHERE
u.location = '$location'
Note, that since you already use bindings, you can also pass $location in a bind parameter. I leave this to you, since it's not part of the question. ;-)

MySQL conditionally populate column 3 based on DISTINCT involving 2 other columns in one table

Had a good read through similar topics but I can't quite a) find one to match my scenario, or b) understand others enough to fit / tailor / tweek to my situation.
I have a table, the important fields being;
+------+------+--------+--------+
| ID | Name | Price |Status |
+------+------+--------+--------+
| 1 | Fred | 4.50 | |
| 2 | Fred | 4.50 | |
| 3 | Fred | 5.00 | |
| 4 | John | 7.20 | |
| 5 | John | 7.20 | |
| 6 | John | 7.20 | |
| 7 | Max | 2.38 | |
| 8 | Max | 2.38 | |
| 9 | Sam | 21.00 | |
+------+------+--------+--------+
ID is an auto-incrementing value as records get added throughout the day.
NAME is a Primary Key field, which can repeat 1 to 3 times in the whole table.
Each NAME will have a PRICE value, which may or may not be the same per NAME.
There is also a STATUS field that need to be populated based on the following, which is actually the part I am stuck on.
Status = 'Y' if each DISTINCT name has only one price attached to it.
Status = 'N' if each DISTINCT name has multiple prices attached to it.
Using the table above, ID's 1, 2 and 3 should be 'N', whilst 4, 5, 6, 7, 8 and 9 should be 'Y'.
I think this may well involve some form of combination of JOINs, GROUPs, and DISTINCTs but I am at a loss on how to put that into the right order for SQL.
In order to get the count of distinct Price values per name, we must use a GROUP BY on the Name field, but since you also want to display all names ungrouped but with an additional Status field, we must first create a subselect in the FROM clause which groups by the name and determines whether the name has multiple price values or not.
When we GROUP BY Name in the subselect, COUNT(DISTINCT price) will count the number of distinct price values for each particular name. Without the DISTINCT keyword, it would simply count the number of rows where price is not null.
In conjunction with that, we use a CASE expression to insert N into the Status column if there is more than one distinct Price value for the particular name, otherwise, it will insert Y.
The subselect only returns one row per Name, so to get all names ungrouped, we join that subselect to the main table on the condition that the subselect's Name = the main table's Name:
SELECT
b.ID,
b.Name,
b.Price,
a.Status
FROM
(
SELECT Name, CASE WHEN COUNT(DISTINCT Price) > 1 THEN 'N' ELSE 'Y' END AS Status
FROM tbl
GROUP BY Name
) a
INNER JOIN
tbl b ON a.Name = b.Name
Edit: In order to facilitate an update, you can incorporate this query using JOINs in the UPDATE like so:
UPDATE
tbl a
INNER JOIN
(
SELECT Name, CASE WHEN COUNT(DISTINCT Price) > 1 THEN 'N' ELSE 'Y' END AS Status
FROM tbl
GROUP BY Name
) b ON a.Name = b.Name
SET
a.Status = b.Status
Assuming you have an unfilled Status column in your table.
If you want to update the status column, you could do:
UPDATE mytable s
SET status = (
SELECT IF(COUNT(DISTINCT price)=1, 'Y', 'N') c
FROM (
SELECT *
FROM mytable
) s1
WHERE s1.name = s.name
GROUP BY name
);
Technically, it should not be necessary to have this:
FROM (
SELECT *
FROM mytable
) s1
but there is a mysql limitation that prevents you to select from the table you're updating. By wrapping it in parenthesis, we force mysql to create a temporary table and then it suddenly is possible.

Mysql SELECT not working

I have the tables:
users
ID | RANK | NAME | EMAIL | PASS
01 | 1 | Foo | foo#bar.com | $06$uhAMXXZowVIDQ.ZR1gky.u3f/UBkLW8Kd8cbyDt2eNx1qnZH2AUmW
allow
ID | RANK | STEP
01 | 1 | 1
02 | 1 | 2
03 | 1 | 3
04 | 2 | 1
05 | 4 | *
And, I need to know all allowed steps from user rank.
My code:
SELECT users.*, allow.step AS allow_step
FROM users AS users LEFT JOIN allow ON users.rank = allow.rank
But only one step are selected.
Thanks for help!
SELECT u.*, GROUP_CONCAT(a.step) allow_step
FROM users u
LEFT JOIN allow a
ON u.rank = a.rank
GROUP BY a.rank_id
This should select a list of steps separated by commas. Something like 1,2,3.
If you need the concatenated values to be ordered, change the first line of the query to:
SELECT u.*, GROUP_CONCAT(a.step ORDER BY a.step) allow_step
The given SQL and data will yield three rows - and would even without the use of a LEFT JOIN (a simple JOIN would suffice).
You don't show or describe how you are running the SQL; do you need to fetch multiple rows in a loop, or use some 'fetch all rows' method?