Query returning data about nested elements - mysql

I have three tables in my database:
boards: idBoard, nameBoard, author
sections: idSection, nameSection, idBoard
tasks: idTask, nameTask, idSection
My query looks like this:
SELECT tasks.idTask, sections.idSection, (more...)
FROM `tasks`
INNER JOIN `boards` ON tasks.idBoard = boards.idBoard
INNER JOIN `sections` ON sections.idSection = tasks.idSection
WHERE boards.idBoard = ?
AND boards.author= ?
The query works almost well, but it doesn't return sections that don't have their tasks items.
Unfortunately, I don't really know why it works like that. I would also like to get section items matching boards but not having tasks items

I think you want outer joins, which usually means left join. Based on the way you describe your tables, I would expect the query to look like this:
SELECT t.idTask, s.idSection, (more...)
FROM boards b LEFT JOIN
sections s
ON b.idBoard = s.idBoard
tasks t
ON s.idSection = t.idSection
WHERE b.idBoard = ? AND boards.author= ?

I think you made a mistake in your query. tasks table doesn't have a column called 'idBoard' in your post.
How about this?
SELECT tasks.idTask, sections.idSection, (more...)
FROM `tasks`
INNER JOIN `sections` ON sections.idSection = tasks.idSection
INNER JOIN `boards` ON sections.idBoard = boards.idBoard
WHERE boards.idBoard = ?
AND boards.author= ?
Could you explain more about what you want?

Related

Combining EXISTS and LEFT JOIN

I need some help combining two queries I wrote( I do not know if it is possible to do it or not). But first let me show you the table and exaplin it so there are no ambiguous angles here.
This is the table I have (PS : I do not know how to make decent looking tables in StackOverflow even though I researched it, and tried to use Senseful solutions so please excuse the image) :
Main Table
The first query I have is the following :
SELECT *
FROM Dropship As t1
WHERE t1.HUB_SO_GOODS_ISSUE_DATE IS NULL
AND EXISTS (SELECT * FROM Dropship t2
WHERE t2.LE_PO = t1.LE_PO
AND t2.HUB_SO_GOODS_ISSUE_DATE IS NOT NULL);
This query gives me all orders that have not have been fully processed. So with the table I have it gives me the orders (LE_PO) 300 and 500 like in the following image :
result from first query
Another query I use is the left join one :
SELECT Dropship.*, Notes_Replenishment.*
FROM Dropship LEFT JOIN Notes_Replenishment ON Dropship.LE_PO = Notes_Replenishment.LE_PO;
The notes_replenishment table has all the orders (LE_PO) but also comments put in by a user. What I would like to do is to incorporate the left join in to the first query so that it gives me the result (see above) but also the comments from the Notes_replenishment table however I get errors when I tried doing it by myself.
Could somebody give me some pointers on how to combine the two queries?
Thank you all in advance!
SELECT *
FROM Dropship As t1
LEFT JOIN
Notes_Replenishment
ON t1.LE_PO = Notes_Replenishment.LE_PO
WHERE t1.HUB_SO_GOODS_ISSUE_DATE IS NULL
AND EXISTS
(
SELECT *
FROM Dropship t2
WHERE t2.LE_PO = t1.LE_PO
AND t2.HUB_SO_GOODS_ISSUE_DATE IS NOT NULL
)

Using an alias to form an inner join

I have a problem which I cant figure out, and have looked on google and similar questions on here, but they are just not quite the same.
I am trying to build a MySQL Query which has two parts, the first is easy and i have done this fine, as it uses existing relationships, see...
SELECT
clientsites.SiteName,
clients.ClientName,
pafaddresses.PostTown,
pafaddresses.PostCode,
CONCAT("XXXXXXX", Replace(UPPER(pafaddresses.PostCode),' ','')) AS JouneyKeytemp,
clientsites.SiteType
FROM clientsites
INNER JOIN clients ON clientsites.ClientFk = clients.ClientPk
INNER JOIN pafaddresses ON clients.ActualPAF = pafaddresses.id
You will see from this code that an alias is generated which concats two postcodes and looks like xxxxxxxyyyyyy, this does work but for obvious reasons ive removed the actual postcodes.
What I now what to do is to bring in two fields from an unrelated table called Journeys:
SELECT
JourneyKey,
SingleDistance,
SingleTime
FROM journeys
I want to bring in SingleDistance and SingleTime, where the Journey Key = Generated Alias of JourneyKeyTemp.
I have tried adding the following:
INNER JOIN journeys ON JouneyKeytemp = journeys.JourneyKey
But I just keep getting a syntax error.
Any help would be appreciated.
Repeat the expression in join predicate:
INNER JOIN journeys
ON CONCAT("XXXXXXX", Replace(UPPER(pafaddresses.PostCode),' ','')) = journeys.JourneyKey
Or you can create a subquery:
select * from(
SELECT
clientsites.SiteName,
clients.ClientName,
pafaddresses.PostTown,
pafaddresses.PostCode,
CONCAT("XXXXXXX", Replace(UPPER(pafaddresses.PostCode),' ','')) AS JouneyKeytemp,
clientsites.SiteType
FROM clientsites
INNER JOIN clients ON clientsites.ClientFk = clients.ClientPk
INNER JOIN pafaddresses ON clients.ActualPAF = pafaddresses.id)t
INNER JOIN journeys ON t.JouneyKeytemp = journeys.JourneyKey

IF ELSE or CASE in MySQL statement?

This is my MySQL Statement :
select
tableG.id,
TestName,
test_group.Merged as TestGroupMerged,
TestSuiteName,
test_suite.Merged as TestSuiteMerged,
test_case.Deleted as TestCaseDeleted,
Long_image_name as Image,
from
test_table
-- new added line -- inner join Long_image_name on test_B.long_image_id = image_table.long_image_id
inner join Long_image_name on test_A.long_image_id = image_table.long_image_id
where
db_test_id = ?
We are adding the image to another table(test_B) if test_B doesn't contain the image it should look in test_A if test_A also doesn't have it then blank image(nothing).
I am thinking to solve it like this:
IF (test_B.long_image_id IS NULL) THEN
inner join Long_image_name on test_A.long_image_id = image_table.long_image_id
ELSE
inner join Long_image_name on test_B.long_image_id = image_table.long_image_id
I cannot test the implementation yet because the database doesn't have any image files currently. Would using ´CASE´ be a better idea?
Thanks for your time!
You can't make conditional joins like that, but you could do the IF() test at a higher level:
SELECT COALESCE(test_B.long_image_id, test_A.long_image_id)
FROM ...
INNER JOIN ... test_A ...
INNER JOIN ... test_B ...
since you are testing for NULL and joining on IDs im assuming the image would only be in 1 of the 2 tables, which means the two INNER JOIN in the answer by Marc B should be changed to LEFT JOIN
SELECT COALESCE(test_B.long_image_id, test_A.long_image_id)
FROM ...
LEFT JOIN ... test_A ...
LEFT JOIN ... test_B ...
Or....
You should be able to do the following:
select *
from test_table test
inner join Long_image_name image on
(test.long_image_id IS NULL and test_A.long_image_id = image.long_image_id) or
(test.long_image_id IS NOT NULL and test_B.long_image_id = image.long_image_id)
Haven't fully tested it on my end, but it's worth a shot.
Side note, your joins don't look quite right, from my quick glance. Make sure you're joining between both tables right, either by alias or actual table name. You'll have to fix the references in the suggested join based on the same concept.
Side note: I've answered this from the mindset of SQL Server 2000, but should still point you the right way.

Taking one column from MySQL joined tables

I have a query in MySQL and I am making a crystal report by using this.
Now inside the query i have a column called scan_mode and it is coming from gfi_transaction table. This scan_mode I am using in report to suppress some sections. But some times this value is coming null for some transaction ids.
So now I want to take this scan_mode as separate query so that it will work.
Can any one please help how I can modify the below query to take only scan_mode column.
SELECT
cc.cost_center_code AS cccde,
cc.name AS ccnme,gf.scan_mode,
cc.cost_center_id AS ccid,
site.name AS siteme,
crncy.currency_locale AS currency_locale,
cntry.language AS LANGUAGE,
cntry.country_name AS cntrynm,
crncy.decimal_digits AS rnd,
gf.transaction_no AS Serial_No,
brnd.name AS brand_name,
rsn.description AS reason,
gf.comment AS COMMENT,
ts.status_description AS STATUS,
DATE_FORMAT(gf.created_date,'%d/%m/%Y') AS created_date,
gf.created_by AS created_by,
IFNULL(gf.approval_no,'Not authorized') AS Trans_no,
gf.approved_date AS approval_dt,
gf.approved_by AS approved_by,gf.status AS status1,
IFNULL(loc.cost_center_code,cc.cost_center_code) AS cur_location,
gf.document_ref_no,gf.document_ref_type,
,DATE_FORMAT(document_ref_date1,'%d/%m/%Y')) AS invoice_no
FROM
gfi_transaction gf
INNER JOIN gfi_instruction gfn ON (gf.transaction_id=gfn.transaction_id)
INNER JOIN gfi_document_instruction doc ON (gf.ref_transaction_no = doc.document_instruction_id)
INNER JOIN reason rsn ON (gf.reason_id = rsn.reason_id)
INNER JOIN gfi_status ts ON (gf.status = ts.gfi_status_id)
INNER JOIN transaction_type tt ON (gf.transaction_type_id = tt.transaction_type_id)
INNER JOIN brand brnd ON(gf.brand_id=brnd.brand_id)
-- cc details
INNER JOIN cost_center cc ON (brnd.parent_brand = cc.brand_id OR gf.brand_id = cc.brand_id)
INNER JOIN site site ON(cc.site_id = site.site_id)
INNER JOIN country cntry ON (site.country_id = cntry.country_id)
INNER JOIN currency crncy ON (cntry.currency_id=crncy.currency_id)
LEFT OUTER JOIN alshaya_location_details loc ON
(gf.brand_id = loc.brand_id AND loc.cost_center_id = gf.cost_centre_id)
LEFT OUTER JOIN alshaya_location_details locto ON
(locto.cost_center_id = gf.from_cost_center_id)
WHERE
gf.transaction_id='{?TransID}'
AND rsn.transaction_type_id IN (10,11,14)
wow, that's a big query. I ran across a similar problem in a query i was building and found the if syntax to be a solution to my problem. This was also answered in this question: MYSQL SELECT WITHIN IF Statement
$psdb->query = "SELECT count, s.classid,
if (k.sic != k.siccode, k.siccode, s.siccode) as siccode,
if (k.sic != k.siccode, k.sicdesc, s.sicdesc) as sicdesc,
if (k.sic != k.siccode, k.sicslug, s.sicslug) as sicslug
FROM ...
It looks like scan_mode column comes from "gfi_transaction" table which seems to be primary table in your query. If you get null for this column then it means your table itself have NULL value for this column. Taking that separately in a query wont solve your problem. Try replacing null with a default value and handle it in code. You can add default value instead of NULL by using ifnull(scan_mode, 'default')

MYSQL get other table data in a join

I am currently running this SQL
SELECT jm_recipe.name, jm_recipe.slug
FROM jm_recipe
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
This returns the desired results except that I also need to return the name of the category that the recipe I am looking for is in, to do this I tried to add the field in to my SELECT statement and also add the table into the FROM clause,
SELECT jm_recipe.name, jm_recipe.slug, jm_category_name
FROM jm_recipe, jm_category
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
However this just returns no results, what am i doing wrong?
You need to join both tables:
SELECT jm_recipe.name, jm_recipe.slug, jm.category_name
FROM jm_recipe
INNER JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
INNER JOIN jm_category ON jm_recipe.recipe_id = jm_category.recipe_id
WHERE jm_category_recipe.category_id = $cat
I've changed the joins to inner joins as well. You might want to make them both LEFT joins if you have NULLs and want them in the result.
Also, you're vulnerable to SQL Injection by simply copying over $cat.
Here's some PHP specific info for you (I'm assuming you're using PHP.)