Multiple SQL Selects to use values to further the search - mysql

I have a SQL query that gets a single row from the database. I want to ultimately return that row plus additional data that can be searched for with values from the first query's row. The only inital data I have is the magazineId. We will use 41659.
select productid, dispenserid from magazine where magazineid = 41659
Gives me two important data values to work with, in one row: ProductID and dispenserId...
Select MagazineID, dispenserId, ProductID from Magazine where ProductID = *** ProductID *** and dispenserId = ***dispenserId***
I ultimately want to get a new row(s), that is generated by doing searches that give me the data to work with in the first query.
How can one do this?

You could use subqueries:
SELECT MagazineID, DispenserID, ProductID
FROM Magazine
WHERE ProductID = (SELECT ProductID
FROM Magazine
WHERE MagazineID= 41659)
AND DispenserId = (SELECT DispenserID
FROM Magazine
WHERE MagazineID= 41659)
Though I'm not sure why you can't just do this:
SELECT MagazineID, DispenserID, ProductID
FROM Magazine
WHERE MagazineID = 41659

Keep in mind that the magazine with the given ID will certainly match by DispenserID and ProductID, so you can simply do this:
SELECT
M2.MagazineID,
M2.DispenserID,
M2.ProductID
FROM
Magazine M1
INNER JOIN Magazine M2 ON
M2.DispenserID = M1.DispenserID AND
M2.ProductID = M1.ProductID
WHERE
M1.MagazineID = 41659

Related

Mysql: join to include all rows (even where SUM=0)

I have DB with two tables:
rmonth and alternatives
The rmonth is an aggregated table of data for each alternative a complete month - if they have any - otherwise the row don't exist in the rmonth table.
Now I want to join them, and this is my code:
SELECT
COALESCE(rmAntal, 0) AS sumMonth, aID, aText, rmUnitID
FROM
alternatives
LEFT JOIN
rmonth ON aID = rmAltID
WHERE aToQuestID = 4418
AND rmMonth = 3
AND rmYear = 2018
AND rmUnitID IN (10603,10960,10496)
GROUP BY aID, rmUnitID
ORDER BY aID ASC
But it doesn't give me the rows not existing in rmonth.
So this scenario gives me the result as I want it - except that it can't handle where the alternative does not exist for that specific unitID in rmonth.
I want them listed with just 0 in sumMonth.
Unfortunately that's where my MySQL-knowledge is limited.
Thanks.
You could add an OR operator, for example
...
WHERE aToQuestID = 4418 AND rmMonth IS NULL OR (
AND rmMonth = 3
AND rmYear = 2018
AND rmUnitID IN (10603,10960,10496)
)
...
This way, you'll get all your alternatives data, even when it's counter part in rmonth is null.

SQL Checking if a value exists in any column and return the value listed of another column

I'm trying to figure out how I can run a query to check and see if someone is listed under someone else. An example would be like a team. There is a team leader and people under that leader. I need to run a query to see if a name is listed under someone else.
I have a table with the following columns:
ID;
Leader_FirstName;
Leader_LastName;
Member1_FN;
Member1_LN;
Member2_FN;
Member2_LN, etc...
I need to check the whole table and if that name exist as any of the members it would return the value of Leader_FirstName and Leader_LastName.
I've been trying to use a "WHERE EXISTS" Like:
SELECT * FROM team
WHERE EXISTS (SELECT * FROM team
WHERE Member1_FN = '$member_fName' AND Member1_LN = '$member_lName'
OR Member2_FN = '$member_fName' AND Member2_LN = '$member_lName'
OR ... etc...
)
Any ideas?
In my opinion, for this data model, one row records one leader and all members, there is no good way to query it.
SELECT * FROM team
WHERE (Member1_FN = '$member_fName' AND Member1_LN = '$member_lName')
OR (Member2_FN = '$member_fName' AND Member2_LN = '$member_lName')
OR (... etc...
This is equivalent to your SQL, but not good.
I think, this table structure is unreasonable. The number of columns in the table depends on the maximum number of members of the leader. If add some members, you must change the table structure to add some columns. It is not flexible enough.
There are many methods to optimize the structure.
1. One row with one member
Table team with the following columns:
ID
Leader_FirstName
Leader_LastName
Member_FN
Member_LN
Leader info will record at many rows, this is the major disadvantage for this structure. In order to avoid this problem, you can try follow method.
2. Two tables: leader and member
Table leader with following columns:
ID
FirstName
LastName
Table member with following columns:
ID
FirstName
LastName
LeaderID
Now, you can join leader and member to find the leader of members.
3. One table team with relationship
Table team is same with the member as follow:
ID
FirstName
LastName
LeaderID (For leader is NULL)
Now, join team and itself.
Use above structure, how to query? I think, you can concat the FirstName and LastName with an separator char that does not appear in the name to a string, than use IN to compare it, for example:
For 1:
SELECT *
FROM team
WHERE CONCAT_WS(',', Member_FN, Member_LN)
IN (CONCAT_WS(',', '$member1_fName', '$member1_fName'),
CONCAT_WS(',', '$member2_fName', '$member2_fName'),
...etc...)
For 2:
SELECT *
FROM leader, member
WHERE leader.ID = member.LeaderId and CONCAT_WS(',', member.FirstName, member.LastName)
IN (CONCAT_WS(',', '$member1_fName', '$member1_fName'),
CONCAT_WS(',', '$member2_fName', '$member2_fName'),
...etc...)
For 3:
SELECT *
FROM team a, team b
WHERE a.ID = b.LeaderId and CONCAT_WS(',', b.FirstName, b.LastName)
IN (CONCAT_WS(',', '$member1_fName', '$member1_fName'),
CONCAT_WS(',', '$member2_fName', '$member2_fName'),
...etc...)
try this
SELECT * FROM team
WHERE (Member1_FN = '$member_fName' AND Member1_LN = '$member_lName')
OR (Member2_FN = '$member_fName' AND Member2_LN = '$member_lName')
OR (... etc...

MySQL multiple joins and count distinct

I need to write query that joins several tables and I need distinct value from one table based on max count().
These are my tables names and columns:
bands:
db|name|
releases_artists:
release_db|band_db
releases_styles
release_db|style
Relations between tables are (needed for JOINs):
releases_artists.band_db = bands.db
releases_styles.release_db = releases_artists.release_db
And now the query that I need to write:
SELECT b.name, most_common_style
LEFT JOIN releases_artists ra ON ra.band_db = b.db
and here I need to find the most common style from all band releases
JOIN(
SELECT DISTINCT style WHERE releases_styles.release_db = ra.release_db ORDER BY COUNT() DESC LIMIT 1
)
FROM bands b
WHERE b.name LIKE 'something'
This is just a non working example of what I want to accomplish. It would be great if someone could help me build this query.
Thanks in advance.
EDIT 1
Each artist from table bands can have multiple records from releases_artists table based on band_db and each release can have multiple styles from releases_styles based on release_db
So if I search for b.name LIKE '%ray%' it returns something similar to:
`bands`:
o7te|Ray Wilson
9i84|Ray Parkey Jr.
`releases_artists` for Ray Wilson:
tv5c|o7te (for example album `Change`)
78wz|o7te (`The Next Best Thing`)
nz7c|o7te (`Propaganda Man`)
`releases_styles`
tv5c|Pop
tv5c|Rock
tv5c|Alternative Pop/Rock
----
78wz|Rock
78wz|Pop
78wz|Classic Rock
I need style name that repeats mostly from all artist releases as this artist main style.
Ok, this is a bit of a hack. But the only alternatives I could think of involve heaps of nested subqueries. So here goes:
SELECT name
, SUBSTRING_INDEX(GROUP_CONCAT(style ORDER BY release_count DESC SEPARATOR '|'), '|', 1) AS most_common_style
FROM (
SELECT b.db
, b.name
, rs.style
, COUNT(*) AS release_count
FROM bands b
JOIN releases_artists ra ON ra.band_db = b.db
JOIN releases_styles rs ON rs.release_db = ra.release_db
GROUP BY b.db, rs.style
) s
GROUP BY db;

select the first row of a joined database

I need to select the first row of a database joined with another main database.
The main database collects informations about dogs, their race, size, name eccc…
The joined database is linked to the frist and provide dog’s images.
Each dog has different images, more than one.
In the list page of the dogs, I need to show, for each dog, all dog’s details and only the frist image of the joined database, as it was the profile image.
So here u are the structure of the two databases:
//dog_pages database:
id
--
slug
--
name
--
race
--
size
--
description
--
created
--
updated
and:
//dog_images database:
id
--
dog_page_id //this is for the join
--
content
--
img_title
--
img_url
--
img_ftp_path
--
thumb_ftp_path
--
thumb_delete_path
I use this code to generate the query:
SELECT dog_pages.id, dog_pages.slug, dog_pages.name, dog_pages.race, dog_pages.size, dog_pages.description, dog_pages.created, dog_pages.updated, dog_images.id, dog_images.dog_page_id, dog_images.img_url, dog_images.thumb_ftp_path, dog_images.content AS image_content
FROM dog_pages
LEFT JOIN dog_images
ON dog_pages.id = (
SELECT dog_images.dog_page_id
FROM dog_images
WHERE dog_pages.id = dog_images.dog_page_id
LIMIT 1
)
Unfortunately this doesn’t work, the results is to have more than one image for each dog. I needjust one, that in the frist row of the dog_images.
There are multiple methods (including variables). But, taking your method, you can use an aggregation function instead of limit:
SELECT p.id, p.slug, p.name, p.race, p.size, p.description, dog_pages.created, p.updated,
i.id, i.dog_page_id, i.img_url, i.thumb_ftp_path, dog_images.content AS image_content
FROM dog_pages p LEFT JOIN
dog_images i
ON p.id = i.dog_page_id AND
i.id = (SELECT MIN(i2.id)
FROM dog_images i2
WHERE p.id = i2.dog_page_id
);
In the second select you are choosing only Id for joining and you can replace it just with
..=dog_images.dog_page_id
It's exactly what you get from the select
To solve the problem try to use group by dog_pages_I'd
And you should get information only about one image

Counting the number min records within groups

I'm building a report for a database where I need to determine the number of "first scans" grouping by company, job, and date.
The scan table can contain multiple scans for the same item, however I only want to include the original scan in my COUNT, which can only be identified as being the scan with the earliest date that matches a particular item.
My first attempt at this was:
SELECT
_item_detail.job_id,
_item_group.group_id,
_scan.company_id,
DATE(scan_date_time) as scan_date,
COUNT(1)
FROM _scan
INNER JOIN _item_detail ON _item_detail.company_id = _scan.company_id
AND
_item_detail.serial_number = _scan.serial_number
INNER JOIN _item_group ON _item_group.group_id = _item_detail.group_id
WHERE _item_detail.job_id = '0326FCM' AND _scan.company_id = '152345' AND _item_group.group_id = 13
GROUP BY
_item_detail.job_id,
_item_group.group_id,
_scan.company_id, scan_date -- first_scan_count
HAVING min(scan_date_time);
This is giving me incorrect results, though (about 3x too many). I am assuming it's because the MIN record is being recalculated for each date, so if the min was found on day 1, it may also be found on day 3 and counted again.
How can I modify my query to achieve the desired results?
Something similar to this should work... I'm not completely sure of how your tables are laid out or how the data relates them together, but this is the general idea:
SELECT
_item_detail.job_id,
_item_group.group_id,
_scan.company_id,
DATE(scan_date_time) as scan_date,
COUNT(1)
FROM
_scan s1
INNER JOIN _item_detail
ON _item_detail.company_id = s1.company_id
AND _item_detail.serial_number = s1.serial_number
AND _item_detail.job_id = '0326FCM'
INNER JOIN _item_group
ON _item_group.group_id = _item_detail.group_id
AND _item_group.group_id = 13
WHERE
s1.company_id = '152345'
AND s1.scan_date_time = (
SELECT MIN(s2.scan_date_time)
FROM _scan s2
WHERE
s2.company_id = s1.company_id
AND s2.serial_number = s1.serial_number
)
GROUP BY
_item_detail.job_id,
_item_group.group_id,
s1.company_id
I don't quite follow your query, but based on the description of the problem, I'd say create a subquery that gives the min scan date for for each item, group by items, the perform your outer select on that.