IF... ELSE statement in mySQL - mysql

Can anyone help me to fix the error? I'm still new with mySQL. The error is at if else statement.
select idpersonal,fname,lname,city from fathi.personal where city='QS';
if (fname=A%) then
begin
select idorder,order_no,item_total from fathi.order;
else
update fathi.order
set item_total=0
where personal.idpersonal=order.idpersonal;

IF is not a valid SQL statement in MySQL.
There's three separate statements here, a SELECT from personal, a SELECT from order (which returns all rows from the table), and an UPDATE statement that has a predicate that references a column from an unknown rowsource.
Here are some examples of SQL based on what was posted in the question.
1) return all rows from personal with city='Q5'
SELECT p.idpersonal
, p.fname
, p.lname
, p.city
FROM fathi.personal p
WHERE p.city='QS';
2) return all rows from order that are related to personal with city='Q5' and fname starting with 'A'. (This only returns rows from personal that are related to an order.)
SELECT o.idorder
, o.order_no
, o.item_total
, p.idpersonal
, p.fname
, p.lname
, p.city
FROM fathi.order o
JOIN fathi.personal p
ON p.idpersonal = o.idpersonal
AND p.city = 'Q5'
AND p.fname LIKE 'A%' ;
3) Modify the contents of table "order", to set the item_total to zero, for all rows that are related to personal with city=`Q5' and have fname not starting with 'A'
UPDATE order o
JOIN personal p
ON p.idpersonal = o.idpersonal
AND p.city = 'Q5'
AND (p.fname IS NULL OR p.fname NOT LIKE 'A%') ;
SET o.item_total=0
Those are just examples. We're just guessing at what you are trying to achieve.

Related

NOT LIKE on mysql query

I have a big problem understanding why a query works when using LIKE in query and not working when using NOT LIKE.
I will post query below:
select DISTINCT (mails), name
from disposable
JOIN (
SELECT DISTINCT (mail) as mails,
CONCAT(toys.firstname, ' ' , toys.lastname) as name
FROM toys2
join toys ON toys.userid = toys2.id
where ( (toyid = '27' or toyid = '29')
and status != 'Sold'
and toys.regdate >= '2017-01-01'
)
) as tab
WHERE tab.mails LIKE CONCAT('%#', disposable.email)
I think what you want is something more like the following. Note that I simplified the schema a bit so as to do a bit less work for the SQL Fiddle.
SELECT c.email, c.name
FROM customer c LEFT JOIN disposable d
ON SUBSTR(c.email, INSTR(c.email, '#')+1, LENGTH(c.email)-INSTR(c.email, '#')) = d.email
WHERE d.email IS NULL;
Basically, here you're getting the domain of the customer and matching it to the entry in the disposable table. The final WHERE clause uses IS NULL to determine the customer email addresses that are not disposable - use IS NOT NULL to find the ones that are.
Hope this helps.

Single SQL to retrieve different information from different tables

I have this query which retrives 10 ( $limited ) queries from MySQL ,
"SELECT content.loc,content.id,content.title,
voting_count.up,voting_count.down
FROM
content,voting_count
WHERE names.id = voting_count.unique_content_id
ORDER BY content.id DESC $limit"
This query did great for posts that were allready in database and had votes , however new posts won't show.
Vote row is "inserted" first time someone votes on post. I guess that the reason why they won't be listed as there is no unique_content_id to connect to.
If i change query into this :
"SELECT content.loc,content.id,content.title
FROM
content
ORDER BY content.id DESC $limit"
it works , but i can't access voting_count.up & voting_count.down rows.
How could i access both information in single query ? Is it doable ?
If some data might not exist in one of the tables, instead of using INNER JOIN you should use LEFT JOIN:
SELECT content.loc,content.id,content.title,
-- USE function COALSESCE will show 0 if there are no
-- related records in table voting_count
COALESCE(voting_count.up, 0) as votes_up,
COALSESCE(voting_count.down, 0) as voted_down
FROM content LEFT JOIN voting_count
ON content.id = voting_count.unique_content_id
ORDER BY content.id DESC
As someone else above mentioned, what is names.id? However, perhaps the following might be of use assuming the join should have been from content.id to voting_count.unique_content_id:
$sql="select
c.`loc`,c.`id`, c.`title`,
case
when v.`up` is null then
0
else
v.`up`
end as 'up',
case
when v.`down` is null then
0
else
v.`down`
end as 'down'
from `content` c
left outer join `voting_count` v on v.`unique_content_id`=c.`id`
order by c.`id` desc {$limit}";

Combining 2 SELECT query using LEFT OUTER JOIN

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.

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.