MySQL select two columns multiple name value pair - mysql

I need help about generating query for multiple column.
part of my tbl_advert_specific_fields_values table look like:
id advert_id field_name field_value
1 654 t1_sqft 50
2 655 t1_yearbuilt 1999
3 1521 t2_doorcount 5
4 656 t1_yearbuilt 2001
5 656 t1_sqft 29
6 654 t1_yearbuilt 2004
SELECT p.*, p.id AS id, p.title AS title, usr.id as advert_user_id,
p.street_num, p.street,c.icon AS cat_icon,c.title AS cat_title,c.title AS cat_title,
p.description as description,
countries.title as country_name,
states.title as state_name,
date_FORMAT(p.created, '%Y-%m-%d') as fcreated
FROM tbl AS p
LEFT JOIN tbl_advertmid AS pm ON pm.advert_id = p.id
INNER JOIN tbl_usermid AS am ON am.advert_id = p.id
LEFT JOIN tbl_users AS usr ON usr.id = am.user_id
INNER JOIN tbl_categories AS c ON c.id = pm.cat_id
INNER JOIN tbl_advert_specific_fields_values AS asfv ON asfv.advert_id = p.id
LEFT JOIN tbl_countries AS countries ON countries.id = p.country
LEFT JOIN tbl_states AS states ON states.id = p.locstate
WHERE p.published = 1 AND p.approved = 1 AND c.published = 1
AND (asfv.field_name = 't1_yearbuilt'
AND CONVERT(asfv.field_value,SIGNED) <= 2004 )
AND (asfv.field_name = 't1_sqft'
AND CONVERT(asfv.field_value,SIGNED) <= 50)
AND p.price <= 10174945 AND (p.advert_type_id = 1)
AND (c.id = 43 OR c.parent = 43)
GROUP BY p.id
ORDER BY p.price DESC
ok, the problem is in this asfv query part that are generated dynamically. It belong to objects which represent adverts by its specific fields. asfv is actually advert_specific_fields_values table (table name say all about it).
Without part:
AND (asfv.field_name = 't1_yearbuilt'
AND CONVERT(asfv.field_value,SIGNED) <= 2004 )
AND (asfv.field_name = 't1_sqft'
AND CONVERT(asfv.field_value,SIGNED) <= 50)
query return all adverts that belong on advert_type_id and price of them are less than 10.174.945,00 €.
All what I need is query update that return only adverts, for example t1_yearbuilt less than 2005 and t1_sqft less than 51 (advert_id => 654,656).
I also need query for values between for example t1_sqft >=30 AND t1_sqft <=50 (advert_id => 654).
Can anybody know how, update this query?
TNX

Related

Displaying data in two separate columns based on where clause in MYSQL

I have a system that has to display a students marks
How can I write my query such that it shows the exam mark and ca mark without showing the zeros, and also be able to properly group by subject ID, not duplicate the subject name
A subject must only appear once with the corresponding CA and Exam mark.
I tried group concat and distinct but no avail.
When I run this query
SELECT
DISTINCT marks.student_id,
GROUP_CONCAT(subjects.subject_name) AS subject_name,
subjects.id as sub_id,
(
CASE WHEN assessements.assessement_type = 1 THEN (
SELECT
ROUND(AVG(marks.mark)) as ca_average
FROM
marks
INNER JOIN assessements ON assessements.id = marks.assessement_id
INNER JOIN teaching_loads ON teaching_loads.id = marks.teaching_load_id
INNER JOIN subjects ON subjects.id = teaching_loads.subject_id
WHERE
marks.student_id = 576
AND assessements.assessement_type = 1
AND assessements.term_id = 2
AND subjects.id = sub_id
ORDER BY
subjects.id
) ELSE 0 END
) as ca,
(
CASE WHEN assessements.assessement_type = 2 THEN (
SELECT
marks.id
FROM
marks
INNER JOIN assessements ON assessements.id = marks.assessement_id
INNER JOIN teaching_loads ON teaching_loads.id = marks.teaching_load_id
INNER JOIN subjects ON subjects.id = teaching_loads.subject_id
WHERE
marks.student_id = 576
AND assessements.term_id = 2
AND assessement_type = 2
AND assessements.term_id = 2
AND subject_id = sub_id
ORDER BY
subjects.id
) ELSE 0 END
) as exam
FROM
marks
INNER JOIN assessements ON assessements.id = marks.assessement_id
INNER JOIN teaching_loads ON teaching_loads.id = marks.teaching_load_id
INNER JOIN subjects ON subjects.id = teaching_loads.subject_id
WHERE
marks.student_id = 576
GROUP BY
subjects.id,
assessements.assessement_type
This is what the query produces
How can I write my query such that it shows the exam mark and ca mark without showing the zeros, be able to properly group by subject ID,
Something like this
**Student ID | Subject Name | sub_id | ca | exam**
576 English 2 40 54
576 Geography 34 30 34
Don't use sub-queries, use conditional aggregation.
SELECT
marks.student_id,
GROUP_CONCAT(subjects.subject_name) AS subject_name,
subjects.id as sub_id,
ROUND(
AVG(
CASE WHEN assessements.assessement_type = 1
AND assessements.term_id = 2
THEN marks.mark
END
)
)
AS ca,
ROUND(
AVG(
CASE WHEN assessements.assessement_type = 2
AND assessements.term_id = 2
THEN marks.mark
END
)
) as exam
FROM
marks
INNER JOIN assessements ON assessements.id = marks.assessement_id
INNER JOIN teaching_loads ON teaching_loads.id = marks.teaching_load_id
INNER JOIN subjects ON subjects.id = teaching_loads.subject_id
WHERE
marks.student_id = 576
GROUP BY
marks.student_id,
subjects.id
CASE expressions that don't have an ELSE implicitly return NULL is none of the WHEN clauses return TRUE.
Also AVG() and other aggregates essentially ignore NULL values. This means that the average of NULL, 1, 2, 3 is 2.
Using these together, the above code returns the average of marks.marks for assessement_type = 1 in one columns, and the average of marks.marks for assessement_type = 2 in a separate column.

How to update records based on condition?

I have a table tbl_loyaltypoints in this table a column status = 2 has default value
Now I have following Query to get all records
select lp.order_id, DATEDIFF(CURDATE(), FROM_UNIXTIME(lp.created_at)) as createon,
oi.deal_id, wo.returnWithin, lp.status
from tbl_loyaltypoints lp
inner join tbl_orders ord on lp.order_id = ord.id
inner join tbl_order_item oi on lp.order_id = oi.order_id
inner join tbl_workorders wo on oi.deal_id = wo.id
where ord.order_type = 1
order by lp.id DESC;
Output:
order_id createon deal_id returnWithin status
1045 4 160 20 2
1044 4 160 20 2
1043 20 160 20 2
I want to update status tbl_loyaltypoints.status when createon==returnWithin.
Is there any way to do this using Mysql?
You can transform the select into a join:
update tbl_loyaltypoints lp inner join
tbl_orders ord
on lp.order_id = ord.id inner join
tbl_order_item oi
on lp.order_id = oi.order_id inner join
tbl_workorders wo
on oi.deal_id = wo.id
set lp.status = ??
where ord.order_type = 1 and
DATEDIFF(CURDATE(), FROM_UNIXTIME(lp.created_at)) = wo.returnWithin;
You don't specify what the new status is. The ?? is a placeholder.

Split multiple count using in mysql with same table

I have a query in below format:
SELECT ETM.etm_Taxonomy, COUNT( PE.pp_profileID ) AS total_counts
FROM expertise_taxonomymaster AS ETM
LEFT JOIN expertise_taxonomy AS ET ON ETM.etm_ID = ET.`et_Taxonomy`
LEFT JOIN expertise AS E ON E.et_Taxonomy = ET.`et_ID`
LEFT JOIN profile_expertise AS PE ON PE.pp_expertiseID = E.et_ID
WHERE PE.pp_profileID IN (
SELECT PJ.pj_profileID
FROM jobtitle_taxonomymaster AS JTM
LEFT JOIN jobtitle_taxonomy AS JT ON JTM.jtm_ID = JT.`jt_Taxonomy`
LEFT JOIN jobtitle AS J ON J.jt_taxonomy = JT.`jt_ID`
LEFT JOIN profile_jobtitle AS PJ ON PJ.pj_jobtitleID = J.jt_ID
WHERE JTM.jtm_Taxonomy = 'Associate'
OR JTM.jtm_Taxonomy = 'Partner'
)
AND et_lawfirmID in (195,196)
GROUP BY etm_Taxonomy
And I have results as follows:
etm_Taxonomy total_counts
Advertising 18
Antitrust 47
Banking 258
But I need below results, Count should be split based on the JTM.ttm_Taxonomy field
etm_Taxonomy Patners195 Partners196 Associates195 Associates196
Advertising 18 18 18 18
Antitrust 47 47 47 47
Banking 258 258 258 258
Try this way:
SELECT ETM.etm_Taxonomy,
SUM (CASE WHEN PJ_TAX.jtm_Taxonomy = 'Associate' THEN 1 ELSE 0 END) AS Associates,
SUM (CASE WHEN PJ_TAX.jtm_Taxonomy = 'Partner' THEN 1 ELSE 0 END) AS Partners,
SUM (CASE WHEN PJ_TAX.jtm_Taxonomy = 'Consultant' THEN 1 ELSE 0 END) AS Consultants,
SUM (CASE WHEN PJ_TAX.jtm_Taxonomy = 'Counsel' THEN 1 ELSE 0 END) AS Counsels,
COUNT(PE.pp_profileID ) AS total_counts
FROM expertise_taxonomymaster AS ETM
LEFT JOIN expertise_taxonomy AS ET ON ETM.etm_ID = ET.`et_Taxonomy`
LEFT JOIN expertise AS E ON E.et_Taxonomy = ET.`et_ID`
LEFT JOIN profile_expertise AS PE ON PE.pp_expertiseID = E.et_ID
INNER JOIN
(
SELECT DISTINCT PJ.pj_profileID,JTM.jtm_Taxonomy
FROM jobtitle_taxonomymaster AS JTM
LEFT JOIN jobtitle_taxonomy AS JT ON JTM.jtm_ID = JT.`jt_Taxonomy`
LEFT JOIN jobtitle AS J ON J.jt_taxonomy = JT.`jt_ID`
LEFT JOIN profile_jobtitle AS PJ ON PJ.pj_jobtitleID = J.jt_ID
WHERE JTM.jtm_Taxonomy = 'Associate'
OR JTM.jtm_Taxonomy = 'Partner'
OR JTM.jtm_Taxonomy = 'Consultant'
OR JTM.jtm_Taxonomy = 'Counsel'
) as PJ_TAX
ON PE.pp_profileID= PJ_TAX.pj_profileID
WHERE et_lawfirmID =195
GROUP BY etm_Taxonomy
First of all: Your left outer joins are no outer joins really, because in your WHERE clause you say you want certain ETs and PEs only.
Mainly you want to join everything, then see whether partner or associate and whether 195 or 196 and count accordingly. This can be done with a CASE construct inside COUNT. Only problem may be duplicates leading to incorrect counts. Im am not completely sure about your database structure. In case there can be duplicate profileIDs with your inner query, you need a derived query with distinct, rather than just joining everything directly. Check if this works for you:
select
etm.etm_taxonomy,
count(case when t.jtm_taxonomy = 'Partner' and et_lawfirmid = 195 then 1 end) as patners195,
count(case when t.jtm_taxonomy = 'Partner' and et_lawfirmid = 196 then 1 end) as patners196,
count(case when t.jtm_taxonomy = 'Associate' and et_lawfirmid = 195 then 1 end) as associates195,
count(case when t.jtm_taxonomy = 'Associate' and et_lawfirmid = 196 then 1 end) as associates196
from expertise_taxonomymaster as etm
join expertise_taxonomy as et on etm.etm_id = et.et_taxonomy
join expertise as e on e.et_taxonomy = et.et_id
join profile_expertise as pe on pe.pp_expertiseid = e.et_id
join
(
select distinct pj.pj_profileid, jtm.jtm_taxonomy
from jobtitle_taxonomymaster as jtm
join jobtitle_taxonomy as jt on jtm.jtm_id = jt.jt_taxonomy
join jobtitle as j on j.jt_taxonomy = jt.jt_id
join profile_jobtitle as pj on pj.pj_jobtitleid = j.jt_id
where jtm.jtm_taxonomy in ('Associate', 'Partner')
) as t on t.pj_profileid = pe.pp_profileid
where et.et_lawfirmid in (195,196);
group by etm.etm_taxonomy;

mysql MAX query not returning latest record on join

I have a query that is returning the correct data except the left join is not returning the latest record (ordering by dateuploaded column) Thanks for any help.
select a.*,p.thumbnailphotopath as Picture from album_access ac
inner join albums a on a.ID = ac.AlbumID
left join (select albumid, thumbnailphotopath,max(DateUploaded) from photos where IsProcessed = 1 and IsPrivate = 0 GROUP BY albumID) p on a.ID = p.AlbumID #photos record not latest
where ac.AccessUserID = ? and ac.Ispending = 0 and ac.FullControl = 1 and a.Private = 1 order by a.DateCreated desc limit ?,?;
List of dates that return desc (its returning 2012-05-01 09:45:43 and thats not the latest)
2012-05-01 09:46:17
2012-05-01 09:46:06
2012-05-01 09:45:43 --Returning this record
2012-05-01 09:45:30
2012-05-01 09:39:49
You need a prequery to get the max date uploaded per album, then can get the correct album entry based on the matching album AND date qualifiers...
select
a.*,
pFinal.thumbnailphotopath as Picture
from
album_access ac
inner join albums a
on ac.AlbumID = a.ID
AND a.Private = 1
left join ( select
p.albumid,
max( p.dateUploaded ) as MaxDate
from
photos p
where
p.IsProcessed = 1
AND p.IsPrivate = 0
group by
p.AlbumID ) pMax
on ac.AlbumID = pMax.AlbumID
left join photos pFinal
on pMax.AlbumID = pFinal.AlbumID
AND pMax.MaxDate = pFinal.DateUpladed
where
ac.AccessUserID = ?
and ac.Ispending = 0
and ac.FullControl = 1
order by
a.DateCreated desc
limit ?,?;

MySQL query returning 0 rows while it should return one

Something is wrong with my MySQL query below but I can't find the problem. It's not returning any errors but the query below should return 1 row, but it returns none.
The table 'fws_product' contains all products. The table 'webits_product_has_kenmerken' contains the product specifications.
SELECT fws_product.*
FROM webits_product_has_kenmerken
LEFT JOIN fws_product ON webits_product_has_kenmerken.product_id = fws_product.ID
WHERE fws_product.CATID = 11
AND (
(webits_product_has_kenmerken.kenmerk_id = 8 AND webits_product_has_kenmerken.kenmerk_value = 'Buddha to Buddha')
AND
(webits_product_has_kenmerken.kenmerk_id = 19 AND webits_product_has_kenmerken.kenmerk_value = '10 mm')
)
Thanks in advance!
It looks a bit nasty, but the following should do as you have requested
SELECT
p.*
FROM fws_product AS p
INNER JOIN webits_product_has_kenmerken AS ps8
ON ps8.product_id = p.ID
AND ps8.kenmerk_id = 8
AND ps8.kenmark_value = 'Buddha to Buddha'
INNER JOIN webits_product_has_kenmerken AS ps19
ON ps19.product_id = p.ID
AND ps19.kenmerk_id = 19
AND ps19.kenmark_value = '10 mm'
WHERE p.CATID = 11
This is another potential option which may do the job, but still feels very nasty
SELECT
p.*
FROM fws_product AS p
INNER JOIN (
SELECT
product_id,
COUNT(*) AS numMatches
FROM webits_product_has_kenmerken
WHERE (kenmerk_id,kenmerk_value) IN (
(8,'Buddha to Buddha'),
(19,'10 mm')
)
GROUP BY product_id
HAVING numMatches = 2
) AS ps
ON ps.product_id = p.ID
WHERE p.CATID = 11
i think you need the following:
SELECT fws_product.*
FROM webits_product_has_kenmerken
LEFT JOIN fws_product ON webits_product_has_kenmerken.product_id = fws_product.ID
WHERE fws_product.CATID = 11
AND (
(webits_product_has_kenmerken.kenmerk_id = 8 AND webits_product_has_kenmerken.kenmerk_value = 'Buddha to Buddha')
OR
(webits_product_has_kenmerken.kenmerk_id = 19 AND webits_product_has_kenmerken.kenmerk_value = '10 mm')
)
checke these columns for NULL values:
fws_product.CATID
webits_product_has_kenmerken.kenmerk_id
webits_product_has_kenmerken.kenmerk_value
every comparison with NULL will exclude the row from the reult