I need to get one value from one table using information from other two.
Here is the structure:
USERS TABLE
+-----------+---------+------------+
| ID | NAME | ZIP |
+-----------+---------+------------+
| 1 | John | 1111-222 |
| 2 | Maria | 2222-555 |
| 3 | José | 3333-505 |
+-----------+---------+------------+
ZIP-MATCH TABLE
+-----------+---------+------------+------------+
| DD | CC | PART1 | PART2 |
+-----------+---------+------------+------------+
| 1 | 1 | 1111 | 101 |
| 1 | 1 | 1111 | 111 |
| 1 | 2 | 1111 | 222 |
| 1 | 3 | 2222 | 333 |
| 2 | 1 | 2222 | 100 |
| 2 | 1 | 2222 | 555 |
| 2 | 2 | 2244 | 222 |
| 2 | 2 | 2244 | 333 |
| 2 | 3 | 2245 | 311 |
| 3 | 1 | 3333 | 111 |
| 3 | 2 | 3333 | 222 |
| 3 | 3 | 3333 | 505 |
+-----------+---------+------------+------------+
AREAS NAME TABLE
+-----------+---------+------------+
| DD | CC | AREA |
+-----------+---------+------------+
| 1 | 1 | Lisboa |
| 1 | 2 | Porto |
| 1 | 3 | Aveiro |
| 2 | 1 | Braga |
| 2 | 2 | Fundão |
| 2 | 3 | Bogas |
| 3 | 1 | Faro |
| 3 | 2 | Leiria |
| 3 | 3 | Covilhã |
+-----------+---------+------------+
What I need to do is a query to get all users from the first table, with all the users data (ID, NAME, ZIP) plus the AREA name.
For this example it would be:
1, John, 1111-222, Porto
2, Maria, 2222-555, Braga
3, José, 3333-505, Covilhã
Thanks in advance,
Miguel.
This is the answer:
SELECT
a.id,
a.name,
a.zip,
c.area
FROM
users a
LEFT JOIN
zip_match b
ON a.zip = concat(b.part1,'-',b.part2)
LEFT JOIN
areas_name c
ON b.dd = c.dd
and b.cc = c.cc;
Assuming your tables were called users, zip_match and areas_name respectively. Not sure of the data types of part1 and part2, they might need to be converted into strings to work in the concat function.
select users.id, users.name, users.zip, areas.area from users u, zipmatch z, areas a
where u.zip = z.part1 + '-' + z.part2
and a.dd = z.dd and a.cc = z.cc
perhaps?
Related
I'm trying to come up with a stored procedure that takes multiple rows that are exactly identical, and combines them into one row while summing one column, which can then be run through more stored procedures based on the sum of that one column.
I've tried a GROUP BY statement, but that doesn't actually group the rows together, because if I run the table through another procedure it performs actions as if each row were not combined. Performing a SELECT * FROM mytable query shows that each row was not actually combined into one.
Is there any way to permanently combine multiple rows into one singular row?
To start, I've got a table like this:
+-------+-----+--------+---------+------+-----+-----------+
| RowID | pID | Name | Date | Code | QTY | Purchased |
+-------+-----+--------+---------+------+-----+-----------+
| 1 | 1 | bob | 9/29/20 | 123 | 1 | |
| 2 | 1 | bob | 8/10/20 | 456 | 1 | |
| 3 | 2 | rob | 9/15/20 | 123 | 1 | |
| 4 | 2 | rob | 9/15/20 | 123 | 1 | |
| 5 | 2 | rob | 9/15/20 | 123 | 1 | |
| 6 | 2 | rob | 9/15/20 | 123 | 1 | |
| 7 | 2 | rob | 9/15/20 | 123 | 1 | |
| 8 | 3 | john | 7/12/20 | 987 | 1 | |
| 9 | 3 | john | 7/12/20 | 987 | 1 | |
| 10 | 4 | george | 9/12/20 | 684 | 1 | |
| 11 | 5 | paul | 2/2/20 | 454 | 1 | |
| 12 | 6 | amy | 1/12/20 | 252 | 1 | |
| 13 | 7 | susan | 5/30/20 | 131 | 1 | |
| 14 | 7 | susan | 6/6/20 | 252 | 1 | |
| 15 | 7 | susan | 5/30/20 | 131 | 1 | |
+-------+-----+--------+---------+------+-----+-----------+
By the end, i'd like to have a table like this:
+-------+-----+--------+---------+------+-----+-----------+
| RowID | pID | Name | Date | Code | QTY | Purchased |
+-------+-----+--------+---------+------+-----+-----------+
| 1 | 1 | bob | 9/29/20 | 123 | 1 | |
| 2 | 1 | bob | 8/10/20 | 456 | 1 | |
| 3 | 2 | rob | 9/15/20 | 123 | 5 | |
| 4 | 3 | john | 7/12/20 | 987 | 2 | |
| 5 | 4 | george | 9/12/20 | 684 | 1 | |
| 6 | 5 | paul | 2/2/20 | 454 | 1 | |
| 7 | 6 | amy | 1/12/20 | 252 | 1 | |
| 8 | 7 | susan | 5/30/20 | 131 | 2 | |
| 9 | 7 | susan | 6/6/20 | 252 | 1 | |
+-------+-----+--------+---------+------+-----+-----------+
Where exactly identical rows are combined into one row, and the QTY field is summed, that I can then add purchases to, or make deductions from the quantity as a total. Using GROUP BY statements can achieve this, but when I go to alter the quantity or add purchases to each person, it treats it like the first table, as if nothing was actually grouped.
So you have this table:
| RowID | pID | Name | Date | Code | QTY | Purchased |
+-------+-----+--------+---------+------+-----+-----------+
| 1 | 1 | bob | 9/29/20 | 123 | 1 | |
| 2 | 1 | bob | 8/10/20 | 456 | 1 | |
| 3 | 2 | rob | 9/15/20 | 123 | 1 | |
| 4 | 2 | rob | 9/15/20 | 123 | 1 | |
| 5 | 2 | rob | 9/15/20 | 123 | 1 | |
| 6 | 2 | rob | 9/15/20 | 123 | 1 | |
| 7 | 2 | rob | 9/15/20 | 123 | 1 | |
| 8 | 3 | john | 7/12/20 | 987 | 1 | |
| 9 | 3 | john | 7/12/20 | 987 | 1 | |
| 10 | 4 | george | 9/12/20 | 684 | 1 | |
| 11 | 5 | paul | 2/2/20 | 454 | 1 | |
| 12 | 6 | amy | 1/12/20 | 252 | 1 | |
| 13 | 7 | susan | 5/30/20 | 131 | 1 | |
| 14 | 7 | susan | 6/6/20 | 252 | 1 | |
| 15 | 7 | susan | 5/30/20 | 131 | 1 | |
The best way, as has been suggested, is to create a new table with the content of your query, then to rename the old table, and the new table to the original table's name, to check if everything is all right, and to drop the original table if yes.
CREATE TABLE indata_new AS
WITH grp AS (
SELECT
MIN(rowid) AS orowid
, pid
, name
, MAX(date) AS date
, code
, SUM(qty) AS qty
FROM indata
GROUP BY
pid
, name
, code
)
SELECT
ROW_NUMBER() OVER(ORDER BY orowid ASC) AS rowid
, *
FROM grp;
ALTER TABLE indata RENAME TO indata_old;
ALTER TABLE indata_new RENAME TO indata;
-- if "indata" now contains the data you want ...
SELECT * FROM indata;
-- out rowid | orowid | pid | name | date | code | qty
-- out -------+--------+-----+--------+------------+------+-----
-- out 1 | 1 | 1 | bob | 2020-09-29 | 123 | 1
-- out 2 | 2 | 1 | bob | 2020-08-10 | 456 | 1
-- out 3 | 3 | 2 | rob | 2020-09-15 | 123 | 5
-- out 4 | 8 | 3 | john | 2020-07-12 | 987 | 2
-- out 5 | 10 | 4 | george | 2020-09-12 | 684 | 1
-- out 6 | 11 | 5 | paul | 2020-02-02 | 454 | 1
-- out 7 | 12 | 6 | amy | 2020-01-12 | 252 | 1
-- out 8 | 13 | 7 | susan | 2020-05-30 | 131 | 2
-- out 9 | 14 | 7 | susan | 2020-06-06 | 252 | 1
-- you can ...
DROP TABLE indata_old;
How to join these to in one sql statement?
I have these 2 simple tables.
3_Referee_Matches
+------------------------------------+
| ID | CountryCode | RefereeUrlCode |
| 1 | eng | mike-jean |
| 2 | eng | mike-jean |
| 3 | eng | mike-jean |
| 4 | eng | mike-jean |
| 5 | spa | hulo-pape |
| 6 | ita | enri-tolsi |
| 7 | ita | enra-ean |
| 8 | ita | enra-ean |
+------------------------------------+
3_Players
+----------------------------------------------------+
| ID | MatchID | Name | PlayerUrlCode | Yellow |
| 1 | 1 | Mike Bell | mike-bell | 1 |
| 2 | 2 | Mike Bell | mike-bell | 1 |
| 3 | 3 | Thoms Tim | thoms-tim | 1 |
| 4 | 4 | Jean Claod | jean-claod | 0 |
| 5 | 33 | Thoms Tim | thoms-tim | 1 |
| 6 | 44 | Fis Most | fis-most | 0 |
| 7 | 54 | Geni Toens | geni-toens | 1 |
| 8 | 67 | Geni Toens | geni-toens | 1 |
+----------------------------------------------------+
Today i use these 2 select. But need help to combine them into one.
select 1:
SELECT rm.*, p.PlayerUrlCode AS VALUEtoBEusedAGAIN, COUNT(p.ID) AS YellowCounter
FROM 3_Referee_Matches rm
JOIN 3_Players p ON rm.ID = p.MatchID
WHERE rm.CountryCode = 'eng' AND rm.RefereeUrlCode = 'mike-jean'
AND p.Yellow>0
GROUP BY p.Name
select 2:
SELECT COUNT(rm.ID) AS Counter
FROM 3_Referee_Matches rm
JOIN 3_Players p ON rm.ID = p.MatchID
WHERE rm.RefereeUrlCode='mike-jean'
AND p.PlayerUrlCode='VALUEtoBEusedAGAIN'
Result should be like this:
+--------------------------------------+
| Name | YellowCounter | Counter |
| Mike Bell | 2 | 2 |
| Jean Claod | 1 | 1 |
+--------------------------------------+
Showing that Mike Bell Got 2 yellow cards in 2 matches.
Your first query is nearly there. First, remove the extraneous columns from the select clause. count the number of "players" (really player information for each match) and sum their yellow cards.
select
p.name,
sum(yellow) as YellowCounter,
count(p.id) as Counter
from 3_Referee_Matches rm
join 3_Players p on rm.ID = p.MatchID
where rm.CountryCode = 'eng'
and rm.RefereeUrlCode = 'mike-jean'
group by p.name;
+------------+---------------+---------+
| name | YellowCounter | Counter |
+------------+---------------+---------+
| Mike Bell | 2 | 2 |
| Thoms Tim | 1 | 1 |
| Jean Claod | 0 | 1 |
+------------+---------------+---------+
I assume the example has Thoms and Jean reversed.
I have a simple MySQL table as such:
| CUST_ID | VISIT | PROD_ID |
|---------|-------|---------|
| 1 | 1 | 3473 |
| 1 | 2 | 324 |
| 1 | 2 | 324 |
| 2 | 1 | 426 |
| 2 | 2 | 4418 |
| 3 | 1 | 4523 |
| 4 | 1 | 976 |
| 4 | 1 | 86 |
| 4 | 2 | 3140 |
| 4 | 3 | 1013 |
And I would like to transform it to this:
| CUST_ID | VISIT | PROD_IDs |
|---------|-------|----------|
| 1 | 1 | 3473 |
| 1 | 2 | 324, 324 |
| 2 | 1 | 426 |
| 2 | 2 | 4418 |
| 3 | 1 | 4523 |
| 4 | 1 | 976, 86 |
| 4 | 2 | 3140 |
| 4 | 3 | 1013 |
This is kinda an ugly hack, I get it.
I have no idea how to cleanly create such a thing. I've tried a variety of unsuccessful grouping strategies. Even a clue or hint in the right direction would be great. Thanks.
If you're trying to group by cust_id + visit, then you can do that and use a GROUP CONCAT on the PROD_ID field, for example:
SELECT
CUST_ID,
VISIT,
GROUP_CONCAT(PROD_ID) PROD_IDS
FROM
table
GROUP BY
CUST_ID,
VISIT
Reference: GROUP CONCAT
I have the following tables:
clients:
| id | name | code | zone |
--------------------------------
| 1 | client 1 | a1b1 | zone1|
| 2 | client 2 | a2b2 | zone2|
contacts:
| id_contact | first_name | last_name |
----------------------------------------
| 11 | first1 | last1 |
| 22 | first2 | last2 |
| 33 | first3 | last3 |
| 44 | first4 | last4 |
client_contacts:
| id_client | id_contact |
--------------------------
| 1 | 11 |
| 1 | 22 |
| 1 | 33 |
| 2 | 11 |
| 2 | 44 |
offers:
| id_offer | id_client | value |
--------------------------
| 111 | 1 | 100 |
| 222 | 1 | 200 |
| 333 | 1 | 300 |
| 444 | 2 | 400 |
I would like through a optimal select to obtain:
| id_client | name | code | zone | contacts_pers | total_offer_value |
----------------------------------------------------------------------------
| 1 | client 1 | a1b1 | zone1 | first1 last1; | 600 |
first2 last2;
first3 last3;
| 2 | client 2 | a2b2 | zone2 | first1 last1; | 400 |
first4 last4;
I know how to get the desired result with "group_concat" and stored procedures for "total_offer_value". But how to get the desired result from a single efficient select?
SELECT c.id, c.name, c.code, c.zone, GROUP_CONCAT(DISTINCT CONCAT(co.first_name, " ", c.last_name) SEPARATOR ";") AS contact_pers, func_total_offer_value(c.id) AS total_offer_value
FROM clients c
LEFT OUTER JOIN (client_contacts cc, contacts co) ON ( c.id = cc.id_client AND cc.id_contact = co.id_contact )
GROUP BY c.id
I have these 3 tables like that:
lecturers:
+-------------+---------+
| id-lecturer | name |
+-------------+---------+
| 1 | Johnson |
| 2 | Smith |
| ... | ... |
| ... | ... |
+-------------+---------+
subjects:
+------------+---------+
| id-subject | name |
+------------+---------+
| 1 | Math |
| 2 | Physics |
| ... | ... |
| ... | ... |
+------------+---------+
exams:
+---------+-------------+------------+------------+
| id-exam | id-lecturer | id-subject | date |
+---------+-------------+------------+------------+
| 1 | 5 | 1 | 1990-05-05 |
| 2 | 7 | 1 | ... |
| 3 | 5 | 3 | ... |
| ... | ... | ... | ... |
+---------+-------------+------------+------------+
When i try to do the first SELECT:
SELECT e.`id-lecturer`, e.`id-subject`, COUNT(e.`id-lecturer`) AS `exams-num`
FROM exams e
JOIN subjects s ON e.`id-subject`=s.`id-subject`
JOIN lecturers l ON e.`id-lecturer`=l.`id-lecturer`
GROUP BY e.`id-lecturer`, e.`id-subject`
I get the right answer. It shows something like that:
+-------------+------------+-----------+
| id-lecturer | id-subject | exams-num |
+-------------+------------+-----------+
| 0001 | 1 | 4 |
| 0001 | 3 | 1 |
| 0001 | 4 | 1 |
| 0001 | 5 | 1 |
| 0002 | 1 | 2 |
| 0002 | 2 | 1 |
| 0002 | 4 | 1 |
| 0002 | 6 | 3 |
+-------------+------------+-----------+
Now i want to show only the max number for every lecturer, my code is:
SELECT it.`id-lecturer`, it.`id-subject`, MAX(it.`exams-num`) AS `exams-number`
FROM (
SELECT e.`id-lecturer`, e.`id-subject`, COUNT(e.`id-lecturer`) AS `exams-num`
FROM egzaminy e
JOIN subjects s ON e.`id-subject`=s.`id-subject`
JOIN lecturers l ON e.`id-lecturer`=l.`id-lecturer`
GROUP BY e.`id-lecturer`, e.`id-subject`) it
GROUP BY it.`id-lecturer`
output:
+-------------+------------+--------------+
| id-lecturer | id-subject | exams-number |
+-------------+------------+--------------+
| 0001 | 1 | 4 |
| 0002 | 1 | 3 |
| 0003 | 1 | 2 |
| 0004 | 1 | 5 |
| 0005 | 2 | 1 |
+-------------+------------+--------------+
I get the correct numbers of the max values for each lecturer, but the subjects id doesn't match, it always takes the first row's id. How can I make it to match correctly these two fields in every row?
I guess you can simply use the same query for further conditions like below.
Select t.Lecturer_id,max(t.exams-num) from
(SELECT e.id-lecturer as Lecturer_id, e.id-subject as Subject_id,
COUNT(e.id-lecturer) AS exams-num
FROM exams e
JOIN subjects s ON e.id-subject=s.id-subject
JOIN lecturers l ON e.id-lecturer=l.id-lecturer
GROUP BY e.id-lecturer, e.id-subject ) as t
group by t.Lecturer_id