I am trying to join 3 tables but it looks like I am doing something wrong. Also I am not sure if INNER JOIN is a good idea here because there might be some missing corresponding rows in the other tables, but I would still like them to show up as NULL, then maybe LEFT JOIN would be better, but again, I'm doing something wrong.
A quick summary of the table responses:
SELECT geonameid, name, iso_alpha2, admin1_code
FROM maxmind_cities1000
WHERE name LIKE 'tron%' LIMIT 20;
+-----------+------------------------+------------+-------------+
| geonameid | name | iso_alpha2 | admin1_code |
+-----------+------------------------+------------+-------------+
| 1605268 | Tron | TH | 10 |
| 8949073 | Tronca | IT | 03 |
| 3107444 | Tronchón | ES | 52 |
| 8859151 | Tronconal | MX | 21 |
| 2821000 | Tröndel | DE | 10 |
| 3133880 | Trondheim | NO | 16 |
| 1252408 | Trongsa | BT | 21 |
| 2667264 | Trönninge | SE | 06 |
| 6535739 | Trontano | IT | 12 |
| 2971582 | Tronville-en-Barrois | FR | B2 |
| 3165134 | Tronzano Lago Maggiore | IT | 09 |
| 3165133 | Tronzano Vercellese | IT | 12 |
+-----------+------------------------+------------+-------------+
SELECT iso_alpha2, name
FROM maxmind_countryinfo
WHERE iso_alpha2 = 'NO';
+------------+--------+
| iso_alpha2 | name |
+------------+--------+
| NO | Norway |
+------------+--------+
SELECT code, name_local
FROM maxmind_admin1_codes_ascii
WHERE code = 'NO.16';
+-------+-----------------+
| code | name_local |
+-------+-----------------+
| NO.16 | Sør-Trøndelag |
+-------+-----------------+
So basically I am trying to join these three tables with this query, I have made a special case and said ON admin1.code = 'NO.16'
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
INNER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = 'NO.16'
WHERE city.name LIKE 'tron%' LIMIT 20;
but it gives me all the rows anyways instead of just Trondheim norway, so I am doing something wrong here. I tried switching to LEFT JOIN but get the same result set. I would like the city to show up in the result set even if there are no matching rows in maxmind_admin1_codes_ascii table, the admin code has the format iso_aplha2 '.' admin1_code
+---------+------------------------+--------------+-----------------+
| city_id | city_name | country_name | admin1_code |
+---------+------------------------+--------------+-----------------+
| 1605268 | Tron | Thailand | Sør-Trøndelag |
| 8949073 | Tronca | Italy | Sør-Trøndelag |
| 3107444 | Tronchón | Spain | Sør-Trøndelag |
| 8859151 | Tronconal | Mexico | Sør-Trøndelag |
| 2821000 | Tröndel | Germany | Sør-Trøndelag |
| 3133880 | Trondheim | Norway | Sør-Trøndelag |
| 1252408 | Trongsa | Bhutan | Sør-Trøndelag |
| 2667264 | Trönninge | Sweden | Sør-Trøndelag |
| 6535739 | Trontano | Italy | Sør-Trøndelag |
| 2971582 | Tronville-en-Barrois | France | Sør-Trøndelag |
| 3165134 | Tronzano Lago Maggiore | Italy | Sør-Trøndelag |
| 3165133 | Tronzano Vercellese | Italy | Sør-Trøndelag |
+---------+------------------------+--------------+-----------------+
This is my end result query but still don't understand why it gives me all results when I just want the special case 'NO.16'. And how should I structure my query if I want the cities to show regardless of there are no matching rows in the maxmind_admin1_codes_ascii table? This is what I have so far
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
INNER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = CONCAT(city.iso_alpha2, '.', city.admin1_code)
WHERE city.name LIKE 'tron%' LIMIT 20;
+---------+------------------------+--------------+--------------------+
| city_id | city_name | country_name | admin1_code |
+---------+------------------------+--------------+--------------------+
| 1605268 | Tron | Thailand | Uttaradit |
| 8949073 | Tronca | Italy | Calabria |
| 3107444 | Tronchón | Spain | Aragon |
| 8859151 | Tronconal | Mexico | Puebla |
| 2821000 | Tröndel | Germany | Schleswig-Holstein |
| 3133880 | Trondheim | Norway | Sør-Trøndelag |
| 1252408 | Trongsa | Bhutan | Tongsa |
| 2667264 | Trönninge | Sweden | Halland |
| 6535739 | Trontano | Italy | Piedmont |
| 2971582 | Tronville-en-Barrois | France | Lorraine |
| 3165134 | Tronzano Lago Maggiore | Italy | Lombardy |
| 3165133 | Tronzano Vercellese | Italy | Piedmont |
+---------+------------------------+--------------+--------------------+
This gives the result I want, but I don't think I am doing it right because the result was unexpected with the special case of 'NO.16'. Hope someone can help out!
Not totally sure if I understand what you are trying to do - but maybe this?
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
LEFT OUTER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = CONCAT(city.iso_alpha2, '.', city.admin1_code)
AND admin1.code = 'NO.16'
WHERE city.name LIKE 'tron%' LIMIT 20;
SELECT
city.geonameid as city_id,
city.name as city_name,
country.name as country_name,
admin1.name_local as admin1_code
FROM maxmind_cities1000 as city
INNER JOIN maxmind_countryinfo as country
ON city.iso_alpha2 = country.iso_alpha2
INNER JOIN maxmind_admin1_codes_ascii as admin1
ON admin1.code = city.admin1_code
WHERE city.name LIKE 'tron%' LIMIT 20 AND city.admin1_code = 'NO.16';
Related
I am trying to write a query to return the sum of totalRxCount that is grouped by zipcode.
I have two tables named fact2 and demographic.
My problem is that in the demographic table there are duplicate rows which affects the sum of totalRxCount.
To avoid duplicates I am wanting to only return results where npiNum is distinct.
Right now I have this working but it is grouping by relId (the primary key).
I cannot figure out a way to group by zipcode since this column and totalRxCount are in separate tables.
When I try this I am getting wrong results since it is counting the duplicate rows.
Here is my query. I am wanting to modify this to return results grouped by zipcode instead of relId.
Any input will be greatly appreciated!
SELECT fact2.relID
, SUM(fact2.`totalRxCount`)
FROM fact2
LEFT
JOIN (
SELECT O1.relId, COUNT(DISTINCT O1.npiNum)
FROM demographic As O1
GROUP BY O1.relId
) AS d1
ON d1.`relId` = fact2.relID
LEFT
JOIN (
SELECT O2.relID, Sum(O2.totalRxCount)
FROM fact2 AS O2
GROUP BY O2.relID
) AS p1
ON p1.relID = d1.relId
WHERE (monthEndDate BETWEEN 201911 AND 202010) GROUP BY fact2.relID;
Results:
+-------+---------------------------+
| relID | SUM(fact2.totalRxCount) |
+-------+---------------------------+
| 2465 | 2 |
+-------+---------------------------+
What I've tried
SELECT zipcode, SUM(fact2.`totalRxCount`)
FROM fact2
INNER JOIN demographic ON demographic.relId=fact2.relID
LEFT JOIN (
SELECT O1.`relId`, COUNT(DISTINCT O1.`npiNum`)
FROM demographic As O1
GROUP BY O1.`relId`
) AS d1
ON d1.`relId` = fact2.`relID`
LEFT JOIN (
SELECT O2.`relID`, Sum(O2.`totalRxCount`)
FROM fact2 AS O2
GROUP BY O2.`relID`
) AS p1
ON p1.`relID` = d1.`relId`
WHERE (`monthEndDate` BETWEEN 201911 AND 202010) GROUP BY zipcode;
This is returning the sum multiplied by number of duplicate rows in demographic.
Results:
+---------+---------------------------+
| zipcode | SUM(fact2.`totalRxCount`) |
+---------+---------------------------+
| 66097 | 4 |
+---------+---------------------------+
^ This should be 2
demographic table:
+-------+---------+------------+------------+-----------+------------+------------------------------------+-------+----------+----------+-----------------+------------+-------+--------------+---------+----------+-----------+--------+-------------+--------+--------+----------------+
| relId | zipcode | providerId | writerType | firstName | middleName | lastName | title | specCode | specDesc | address | city | state | amaNoContact | pdrpInd | pdrpDate | deaNum | amaNum | amaCheckDig | npiNum | terrId | callStatusCode |
+-------+---------+------------+------------+-----------+------------+------------------------------------+-------+----------+----------+-----------------+------------+-------+--------------+---------+----------+-----------+--------+-------------+--------+--------+----------------+
| 2465 | 66097 | | A | | | JEFFERSON COUNTY MEMORIAL HOSPITAL | | | | 408 DELAWARE ST | WINCHESTER | KS | | | | AJ4281096 | | | | 11604 | |
| 2465 | 66097 | | A | | | JEFFERSON COUNTY MEMORIAL HOSPITAL | | | | 408 DELAWARE ST | WINCHESTER | KS | | | | AJ4281096 | | | | 11604 | |
+-------+---------+------------+------------+-----------+------------+------------------------------------+-------+----------+----------+-----------------+------------+-------+--------------+---------+----------+-----------+--------+-------------+--------+--------+----------------+
fact2
+-------+----------+-----------------+-----------+-------------------+----------+------------+------------+--------+------------+--------------+------------+---------------+--------------+-----------+--------------+-------------+-----------+--------------+-------------+
| relID | marketId | marketName | productID | productName | dataType | providerId | writerType | planId | pmtTypeInd | monthEndDate | newRxCount | refillRxCount | totalRxCount | newRxQuan | refillRxQuan | totalRxQuan | newRxCost | refillRxCost | totalRxCost |
+-------+----------+-----------------+-----------+-------------------+----------+------------+------------+--------+------------+--------------+------------+---------------+--------------+-----------+--------------+-------------+-----------+--------------+-------------+
| 2465 | 10871 | GALT PP MONTHLY | 1399451 | ZOLPIDEM TARTRATE | 15 | | A | 900145 | C | 202004 | 1 | 0 | 1 | 30 | 0 | 30 | 139 | 0 | 139 |
| 2465 | 10871 | GALT PP MONTHLY | 1399458 | ESZOPICLONE | 15 | | A | 900145 | C | 202006 | 1 | 0 | 1 | 30 | 0 | 30 | 350 | 0 | 350 |
+-------+----------+-----------------+-----------+-------------------+----------+------------+------------+--------+------------+--------------+------------+---------------+--------------+-----------+--------------+-------------+-----------+--------------+-------------+
I have this query:
SELECT c.`id`, w.`qty`, COUNT(c.`id`) AS pieces, c.`location`
FROM `control` AS c
LEFT JOIN `warehouse` AS w ON w.`id` = c.`id`
WHERE c.`code` = '40'
GROUP BY c.`id`
I have these tables:
`control` c `warehouse` w
+----+--------+------+----------+ +------+-------+
| id | pieces | code | location | | id | qty |
+----+--------+------+----------+ +------+-------+
| 112| 112-1 | 40 | london | | 112 | 3 |
| 112| 112-2 | 40 | london | | 113 | 3 |
| 112| 112-3 | 40 | london | | 114 | 1 |
| 113| 113-1 | 40 | italy | | 115 | 1 |
| 113| 113-2 | 40 | italy | +--------------+
| 113| 113-3 | 40 | italy |
| 114| 114-1 | 41 | france |
| 115| 115-1 | 41 | france |
| 112| 112-1 | 40 | germany |
| 112| 112-2 | 40 | germany |
| 112| 112-3 | 40 | germany |
| 113| 112-1 | 40 | russia |
| 113| 112-2 | 40 | russia |
| 113| 112-3 | 40 | russia |
| 112| 112-1 | 40 | poland |
| 112| 112-2 | 40 | poland |
| 112| 112-3 | 40 | poland |
+-------------------------------+
Im getting this:
actual output
+-----+-----+--------+----------+
| id | qty | pieces | location |
+-----+-----+--------+----------+
| 112 | 3 | 9 | poland |
| 113 | 3 | 6 | russia |
+-------------------------------+
I'm trying to get this result:
desired output
+-----+-----+--------+----------+
| id | qty | pieces | location |
+-----+-----+--------+----------+
| 112 | 3 | 3 | london |
| 113 | 3 | 3 | italy |
| 112 | 3 | 3 | germany |
| 113 | 3 | 3 | russia |
| 112 | 3 | 3 | poland |
+-------------------------------+
Is possible this result? maybe tweaking my query?
I tried without GROUP BY but in that case i just get 1 row totalizing pieces.
If you want to separate the different locations to different rows, you need to add that column to the group by clause:
SELECT c.`id`, w.`qty`, COUNT(c.`id`) AS pieces, c.`location`
FROM `control` AS c
LEFT JOIN `warehouse` AS w ON w.`id` = c.`id`
WHERE c.`code` = '40'
GROUP BY c.`id`, c.`location`
-- Here ---------^
I suspect that you just need to add qty and location to the group by clause:
SELECT c.`id`, w.`qty`, COUNT(*) AS pieces, c.`location`
FROM `control` AS c
LEFT JOIN `warehouse` AS w ON w.`id` = c.`id`
WHERE c.`code` = '40'
GROUP BY c.`id`, w.`qty`, c.`location`
Starting MySQL 5.7, it is mandatory to list all-non aggregated columns in the group by clause (unless you change default sql option ONLY_FULL_GROUP_BY); most other databases also implement this constraint. I would recommend getting used to it...
Side notes:
COUNT(c.id) is better written COUNT(*), since id seems like a not nullable column
generally spearking, you shoud avoid using backticks around table and column names unless when absolutly necessary.
I want to show some data from the database. The id of the boss is in the same row as an employee. I want to display the name of the boss. eId is the id of the employee and bossId is the id of his boss. recepId is the id of the receptionist of that department.
I want to show the department name, description, id of the receptionist, name of the receptionist, id of the boss and his name.
I can display everything except the name of the boss. How do manage that inside my query?
Employee table:
| eId | name |city |bossId | depNr |
|:-------------|------------:|:------------:|--------------------
| 345 | Frits | Canvas | 240 | 60|
| 240 | Steven | Canvas | 200 | 90|
| 265 | John | Kentucky | 40 | 60|
| 40 | Kreuger | Kentucky | | 90|
Department table:
| depCode | depName |locId |recepId|
|:-------------|------------: |:-----------|----------
| 60 | Finance | CAN | 345 |
| 90 | Research | CAN | 265 |
Location table:
| code | description |country |
|:-------------|------------: |:-----------|
| CAN | Finance | USA |
| CAN | Research | USA |
| KEN | Economics | USA |
What I want:
| depName | description |recepId |name | bossID| bossName|
|:-------------|------------:|:------------:|----------------------------
| 345 | COD12 | Canvas | Frits | 240 | Steven
| 140 | COD40 | Canvas | John | 800 | Kreuger
My query:
SELECT department.depName, Location.description, department.recepId, employee.name, employee.bossId
FROM department
INNER JOIN Location
ON Location.code = department.locId
Left JOIN employee
ON department.recepId = employee.eId
This shows:
| depName | description |recepId |name | bossID|
|:-------------|------------:|:------------:|-------------------
| 345 | COD12 | Canvas | Frits | 240 |
| 140 | COD40 | Canvas | John | 800 |
Join with employee again to get the boss's name.
SELECT department.depName, Location.description, department.recepId,
employee.name, employee.bossId, boss.name AS bossName
FROM department
INNER JOIN Location
ON Location.code = department.locId
Left JOIN employee
ON department.recepId = employee.eId
LEFT JOIN employee AS boss
ON employee.bossId = boss.eId
I have two MySql tables, once for "Locations" and one for "Images". I need to get a list of the most recent Image taken at a particular set of Locations (which is a comma-delimited list), but I only want to return the record for the most recent Image and I've been struggling mightily with getting the right results so far.
So, I have:
Locations:
+---------------------------------------------+
| ID | Name |
|----|----------------------------------------|
| 1 | Indiana |
| 2 | Ohio |
| 3 | Illinois |
+---------------------------------------------+
Images:
+---------------------------------------------+
| ID | User | Location | Date |
|----|-------|-----------|--------------------|
| 1 | Ray | 1 | 2012-06-22 |
| 2 | Robert| 3 | 2011-09-18 |
| 3 | Marie | 1 | 2012-10-01 |
| 4 | Frank | 2 | 2010-12-11 |
| 5 | Debra | 1 | 2008-02-02 |
+---------------------------------------------+
So, right now I have the following:
SELECT Locations.Name, Images.Date, Images.User
FROM Locations INNER JOIN Images ON Locations.ID = Images.Location
WHERE Locations.ID IN ('1','3')
ORDER BY Images.Date DESC
Which returns:
+---------------------------------------------+
| Name | Date | User |
|-------------|-------------|-----------------|
| Indiana | 2012-10-01 | Marie |
| Indiana | 2012-06-22 | Ray |
| Illinois | 2011-09-18 | Robert |
| Indiana | 2008-02-02 | Debra |
+---------------------------------------------+
My question is, how can I get it so that the result returns only the first record with a distinct Location.Name value? So the final, correct result table would look like:
+---------------------------------------------+
| Name | Date | User |
|-------------|-------------|-----------------|
| Indiana | 2012-10-01 | Marie |
| Illinois | 2011-09-18 | Robert |
+---------------------------------------------+
Thanks a lot!
SImply uSe group by::
Select tempTable.Name, tempTable.Date, tempTable.User from
(
SELECT Locations.Name, Images.Date, Images.User, Locations.ID as locationID
FROM Locations
INNER JOIN Images ON Locations.ID = Images.Location
WHERE Locations.ID IN ('1','3')
ORDER BY Images.Date DESC
) as tempTable GROUP BY tempTable.locationID
I have two tables like below,
mysql> select * from Books ;
+----+------+------------+----------+----------+
| id | name | author_name| category | category2|
+----+------+------------+----------+----------+
| 1 | 1 | Steve | CT001 | CT003 |
| 2 | 2 | John | CT002 | CT002 |
| 3 | 3 | Larry | CT003 | CT002 |
| 4 | 3 | Michael | CT004 | CT004 |
| 5 | NULL | Steven | CT005 | CT005 |
+----+------+------------+----------+----------+
mysql> select * from Codemst ;
+----+------+------------+
| id | code | name |
+----+------+------------+
| 1 | CT001| fiction |
| 2 | CT002| category1 |
| 3 | CT003| etc |
| 4 | CT004| etc2 |
| 5 | CT005| etc3 |
+----+------+------------+
I want to get human readable category name when I query like "select * from Books;"
If there was only one category in the Books table, I think I can use "Join" but, in this case what can I do?
select * from Books b
Inner Join Codemst c1 on b.category = c1.code
inner join codemst c2 on b.category2 = c2.code;
c1.name will hold the readable category, and c2.name the readable category2