Combining 2 SELECT query using LEFT OUTER JOIN - mysql

How do i combined this to two select query using left join syntax. (My query has error and I can't find a solution)
select
*
from
(select
mi.parent_entity_id entity,
tctp.institution_rec_id institutionRecId,
institution_code storecode,
institution_name storename,
case when sum(unsettled_points) is null
then coalesce (sum(point_value),0)
else coalesce
(sum(unsettled_points),0) end sumpoints
from
t_card_transaction_point tctp
inner join
m_institution mi on tctp.institution_rec_id=mi.institution_rec_id
where
mi.parent_entity_id = 70125 and
tctp.point_status = 'xy4604'
group by
entity,
institutionRecId,
storecode,
storename
) storeExpired
left join
entityExpired on storeExpired.entity=entityExpired.entity
(select
mpb.institution_rec_id entity,
tctd.institution_rec_id institutionRecId,
tctd.card_no cardnumber,
total_amount_primary totalpoints,
case when total_unsettled_points is null
then point_value
else tctd.total_unsettled_points end
points
from
t_card_transaction_detail tctd inner
join
m_point_bucket mpb on mpb.card_no=tctd.card_no
inner join
m_institution mi on mi.institution_rec_id=tctd.institution_rec_id
where
mpb.total_amount_primary > 1000 and
tctd.adjustment_date is null
group by
entity,
institutionRecId,
cardnumber,
totalpoints,
points
) entityExpired

Firstly:
We do appreciate proper indenting / lining of code for ease of readability :)
Second:
"My query has error" is not particularly explanatory.
Anywho, to answer your question:
SQL has an order of operation of
From
Where
Group By
Having
Select
Order By
This means that the alias are created when the select is executed. And since "group by" is executed before this, the alias's doesn't exist yet - this is probably the error you are getting.
Also, I'm not sure if MySQL does allow a join on a alias, which is defined further down in the query (I could be wrong though), so i would move the query itself into the join brackets, and use on the "on"-clause afterwards.
Sample query: (Not tested, since I doesn't have the tables)
select
*
from (
select
mi.parent_entity_id as entity
, tctp.institution_rec_id as institutionRecId
, institution_code as storecode
, institution_name as storename
, case when sum(unsettled_points) is null
then coalesce (sum(point_value),0)
else coalesce (sum(unsettled_points),0)
end as sumpoints
from t_card_transaction_point tctp
inner join m_institution mi on tctp.institution_rec_id = mi.institution_rec_id
where 1=1
and mi.parent_entity_id = 70125
and tctp.point_status = 'xy4604'
group by
mi.parent_entity_id
, tctp.institution_rec_id
, institution_code
, institution_name
) storeExpired
left join (
select
mpb.institution_rec_id as entity
, tctd.institution_rec_id as institutionRecId
, tctd.card_no as cardnumber
, total_amount_primary as totalpoints
, case when total_unsettled_points is null
then point_value
else tctd.total_unsettled_points
end as points
from t_card_transaction_detail tctd
inner join m_point_bucket mpb on mpb.card_no=tctd.card_no
inner join m_institution mi on mi.institution_rec_id=tctd.institution_rec_id
where 1=1
and mpb.total_amount_primary > 1000
and tctd.adjustment_date is null
group by
mpb.institution_rec_id
, tctd.institution_rec_id
, tctd.card_no
, total_amount_primary
, case when total_unsettled_points is null
then point_value
else tctd.total_unsettled_points
end
) entityExpired on storeExpired.entity=entityExpired.entity
Edit:
I just google'd it, and you can in fact use alias's in your group by statement in MySQL (Not allowed in MSSQL, nor is it ANSI standard).
However, after seeing your comment regarding the error, it is probably due to the fact that you are joining with the alias entityExpired, before the subquery is created. I'm guessing that moving the subquery, as I've done in the example, should work.

Related

Query gets very slows if i add a where

SELECT a.emp_id,s.name, s.department,s.register, z.Compoff_Count as Extra, ifnull(COUNT(DISTINCT TO_DAYS(a.punchdate)),0) as Monthly_Count
FROM machinedata a left join
(SELECT a.emp_id, ifnull(COUNT(DISTINCT TO_DAYS(a.punchdate)),0) as Compoff_Count
FROM machinedata a
RIght JOIN time_dimension c on c.db_date = a.punchdate
where ( year(c.db_date) = 2016 and month(c.db_date) = 8 and (c.holiday_flag = 't' or c.weekend_flag ='t' ))
GROUP BY a.emp_id) Z
on z.emp_id = a.emp_id
RIght JOIN time_dimension c on c.db_date = a.punchdate
left join emp s on s.emp_id = a.emp_id
where (year(c.db_date) = 2016 and month(c.db_date) = 8 and c.holiday_flag = 'f' and c.weekend_flag ='f' )
GROUP BY emp_id
The above query works fine.. but if i add s.department='yes' in the last where the query takes more than 40 seconds.
What shall i do to improve the query performance ?
Your initial query can be simplified I believe by using "conditional aggregates" which places case expressions inside the count() function. This avoids repeated sans of data and unnecessary joins to derived tables.
You should also avoid using functions on data to suit where clause conditions i.e. Instead of YEAR() and MONTH() simply use date boundaries. This allows an index on the date column to be used in the query execution.
I'm not sure if you really need to use TO_DAYS() but I suspect it isn't needed either.
SELECT
a.emp_id
, s.name
, s.department
, s.register
, COUNT(DISTINCT CASE WHEN (c.holiday_flag = 't' OR
c.weekend_flag = 't') THEN c.db_date END) AS Compoff_Count
, COUNT(DISTINCT CASE WHEN NOT (c.holiday_flag = 't' OR
c.weekend_flag = 't') THEN a.punchdate END) AS Monthly_Count
FROM time_dimension c
LEFT JOIN machinedata a ON c.db_date = a.punchdate
LEFT JOIN emp s ON a.emp_id = s.emp_id
WHERE c.db_date >= '2016-08-01'
AND c.db_date < '2016-09-01'
GROUP BY
a.emp_id
, s.name
, s.department
, s.register
If this re-write produces correct results then you could try adding and s.department='yes' into the where clause to assess the impact. If it is still substantially slower then get an explain plan and add it to the question. The most likley cause of slowness is lack of an index but without an explain plan it's not possible to be certain.
Please note that this suggestion is just that; and is prepared without sample data and expected results.

mysql LEFT JOIN query with max value in where state

ok so I have a database and a query built up something like this
http://sqlfiddle.com/#!2/c03e8/11
however I can't for the world of me figure out how to reach my end goal which is to hide the tenth row as that one has the "tamed" = 1
would anyone please point me in the right direction
simple just do a select of your select and add an additional where
SELECT id, name, level, location, tamed
FROM (
-- your inside select here
) as temp
WHERE temp.tamed <> 1
Use the below query ... 10th row is gone. remove the condition from where clause and add to join condition. Also, I made your first join type is INNER JOIN rather a LEFT JOIN. So that, when the condition doesn't match that row will not be returned at all.
Your fiddle with my updated query here http://sqlfiddle.com/#!2/835b3b/28
SELECT `t1` . * , MAX(
CASE WHEN `info_types`.`name` = "level"
THEN `t1_info`.`value`
ELSE NULL
END ) AS "level",
MAX(
CASE WHEN `info_types`.`name` = "location"
THEN `t1_info`.`value`
ELSE NULL
END ) AS "location",
MAX(
CASE WHEN `info_types`.`name` = "tamed"
THEN `t1_info`.`value`
ELSE NULL
END ) AS "tamed"
FROM `t1`
INNER JOIN `t1_info`
ON `t1`.`id` = `t1_info`.`t1_id`
AND `t1`.`id` !=10
LEFT JOIN `info_types`
ON `t1_info`.`type_id` = `info_types`.`id`
and `t1_info`.`value` !=1
GROUP BY `t1`.`id`;
EDIT:
In your posted fiddle query, change the second left join to look like below, with that the tammed column for 10th row also will be NULL. Else, go for a outer select as suggested in other answer.
LEFT JOIN `info_types`
ON `t1_info`.`type_id` = `info_types`.`id`
AND `t1_info`.`type_id` != 3

sql query with case/COALESCE statement

I have query that working perfectly.but now there is situation where i have to join 2 query in case statement.but problem is one of the query is in already use.So my question how do i add this two sql in one sql
My original sql is
SELECT
tc.dentist_id,md.vendor_no,pl.pack_trans_id,tc.agent_dentist,md.company_name,md.contact,md.phone_no,sql1.image_path,sql1.metal_id,sql1.expect_more,sql1.how_long_acquire,tc.check_amt,tc.check_date_sent,tc.check_no
FROM tbl_check tc
LEFT JOIN tbl_mst_dentist md ON tc.dentist_id=md.dentist_id
LEFT JOIN tbl_pack_list pl ON tc.pack_id=pl.pack_id
LEFT JOIN (SELECT image_path,pack_id,metal_id,expect_more,how_long_acquire FROM
tbl_metals_list GROUP BY pack_id
)sql1 ON tc.pack_id=sql1.pack_id
WHERE tc.sale_agent_id = '3' AND tc.paying_percent !=0
Now i have to add 2 sql statement in the above statement
if(tc.agent_dentist=a) select sa.* ,sm.state_code from tbl_sales_agent
as sa,tbl_mst_state as sm where sa.sales_agent_id = '3' AND
sa.state=sm.state_name else select * from tbl_mst_dentist where
dentist_id =tc.dentist_id
second table already is in use.Is it possible? Thanks in advance
yes, you can use an ALIAS with a different name. E.g. TABLE AS ANY_ALIAS.
SELECT *
FROM t1
JOIN t2 AS alias_a ON (alias_a.t1_id = t1.id)
JOIN t2 AS alias_b ON (alias_b.t1_id = t1.id)
Note that in the absence of any aggregating functions, the use of GROUP BY in this query...
SELECT image_path
, pack_id
, metal_id
, expect_more
, how_long_acquire
FROM tbl_metals_list
GROUP
BY pack_id
...makes little sense. Perhaps you meant SELECT DISTINCT...?

SELECT CASE WHEN THEN (SELECT)

I am trying to select a different set of results for a product depending on a product type.
So if my product should be a book I want it to look up the UPC and Artist for a normal product these details are however irrelevant and for another product I would want a completely different set of results.
SELECT CASE Product.type_id
WHEN 10 THEN (
SELECT
Product.product_id,
Product.type_id,
Product.product_name,
Product.UPC,
Product_Type.type,
CONCAT_WS(' ' , first_name, middle_name, last_name ) AS artistC
FROM Product, Product_Type, Product_ArtistAuthor
WHERE Product.type_id = Product_Type.type_id
AND Product.product_id = $pid
AND Product.artist_id = Product_ArtistAuthor.artist_id
)
ELSE (
SELECT
Product.product_id,
Product.type_id,
Product.product_name,
Product_Type.type
FROM Product, Product_Type
WHERE Product.type_id = Product_Type.type_id
AND Product.product_id = $pid
)
END
FROM Product
WHERE Product.product_id = $pid
I am not sure where I am going wrong
You Could try the other format for the case statement
CASE WHEN Product.type_id = 10
THEN
(
Select Statement
)
ELSE
(
Other select statement
)
END
FROM Product
WHERE Product.product_id = $pid
See http://msdn.microsoft.com/en-us/library/ms181765.aspx for more information.
You should avoid using nested selects and I would go as far to say you should never use them in the actual select part of your statement. You will be running that select for each row that is returned. This is a really expensive operation. Rather use joins. It is much more readable and the performance is much better.
In your case the query below should help. Note the cases statement is still there, but now it is a simple compare operation.
select
p.product_id,
p.type_id,
p.product_name,
p.type,
case p.type_id when 10 then (CONCAT_WS(' ' , first_name, middle_name, last_name )) else (null) end artistC
from
Product p
inner join Product_Type pt on
pt.type_id = p.type_id
left join Product_ArtistAuthor paa on
paa.artist_id = p.artist_id
where
p.product_id = $pid
I used a left join since I don't know the business logic.
For a start the first select has 6 columns and the second has 4 columns. Perhaps make both have the same number of columns (adding nulls?).
I ended up leaving the common properties from the SELECT queries and making a second SELECT query later on in the page. I used a php IF command to call for different scripts depending on the first SELECT query, the scripts contained the second SELECT query.

mysql update query with sub query

Can anyone see what is wrong with the below query?
When I run it I get:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'a where a.CompetitionID = Competition.CompetitionID' at line 8
Update Competition
Set Competition.NumberOfTeams =
(
SELECT count(*) as NumberOfTeams
FROM PicksPoints
where UserCompetitionID is not NULL
group by CompetitionID
) a
where a.CompetitionID = Competition.CompetitionID
The main issue is that the inner query cannot be related to your where clause on the outer update statement, because the where filter applies first to the table being updated before the inner subquery even executes. The typical way to handle a situation like this is a multi-table update.
Update
Competition as C
inner join (
select CompetitionId, count(*) as NumberOfTeams
from PicksPoints as p
where UserCompetitionID is not NULL
group by CompetitionID
) as A on C.CompetitionID = A.CompetitionID
set C.NumberOfTeams = A.NumberOfTeams
Demo: http://www.sqlfiddle.com/#!2/a74f3/1
Thanks, I didn't have the idea of an UPDATE with INNER JOIN.
In the original query, the mistake was to name the subquery, which must return a value and can't therefore be aliased.
UPDATE Competition
SET Competition.NumberOfTeams =
(SELECT count(*) -- no column alias
FROM PicksPoints
WHERE UserCompetitionID is not NULL
-- put the join condition INSIDE the subquery :
AND CompetitionID = Competition.CompetitionID
group by CompetitionID
) -- no table alias
should do the trick for every record of Competition.
To be noticed :
The effect is NOT EXACTLY the same as the query proposed by mellamokb, which won't update Competition records with no corresponding PickPoints.
Since SELECT id, COUNT(*) GROUP BY id will only count for existing values of ids,
whereas a SELECT COUNT(*) will always return a value, being 0 if no records are selected.
This may, or may not, be a problem for you.
0-aware version of mellamokb query would be :
Update Competition as C
LEFT join (
select CompetitionId, count(*) as NumberOfTeams
from PicksPoints as p
where UserCompetitionID is not NULL
group by CompetitionID
) as A on C.CompetitionID = A.CompetitionID
set C.NumberOfTeams = IFNULL(A.NumberOfTeams, 0)
In other words, if no corresponding PickPoints are found, set Competition.NumberOfTeams to zero.
For the impatient:
UPDATE target AS t
INNER JOIN (
SELECT s.id, COUNT(*) AS count
FROM source_grouped AS s
-- WHERE s.custom_condition IS (true)
GROUP BY s.id
) AS aggregate ON aggregate.id = t.id
SET t.count = aggregate.count
That's #mellamokb's answer, as above, reduced to the max.
You can check your eav_attributes table to find the relevant attribute IDs for each image role, such as;
Then you can use those to set whichever role to any other role for all products like so;
UPDATE catalog_product_entity_varchar AS `v` INNER JOIN (SELECT `value`,`entity_id` FROM `catalog_product_entity_varchar` WHERE `attribute_id`=86) AS `j` ON `j`.`entity_id`=`v`.entity_id SET `v`.`value`=j.`value` WHERE `v`.attribute_id = 85 AND `v`.`entity_id`=`j`.`entity_id`
The above will set all your 'base' roles to the 'small' image of the same product.