I have table data like
value pvalue value_type
an1001 bk1001 1
an1002 null 1
an1003 null 1
an1004 bk1002 1
bk1001 ck1001 2
bk1002 ck1002 2
ck1001 MG1001 3
ck1002 null 3
I m expecting result like
value pvalue1 pvalue2 pvalue2
an1001 bk1001 ck1001 MG1001
an1002 bk1002 ck1002
an1003
an1004
is there any way to write queries where i can avoid left outer join or inner join rather that i can use inline queires
You can use something like the following query. Please mind the syntax errors, if any.
select value,
max(case when value_type = 1 then pvalue else null end) as pvalue1,
max(case when value_type = 2 then pvalue else null end) as pvalue2,
max(case when value_type = 3 then pvalue else null end) as pvalue3
from table
group by value;
Please help to find out the result.How to a write a query to combine rows which has same id
id size sizeorder color colororder
1 M 1 null null
1 null null red 1
2 s 1 null null
2 Null null green 2
output should be
id size sizeorder color colororder
1 M 1 red 1
2 s 1 green 2
SELECT id,
MAX(size) AS size,
MAX(sizeorder) AS sizeorder,
MAX(color) AS color,
MAX(colororder) AS colororder
FROM yourTable
GROUP BY id
The rollup you are trying to do is similar to what happens in a pivot query. The "secret sauce" in the above query is that MySQL's MAX function ignores NULL values. This means that in your table only the non NULL values will be retained in each column, for each grouped id.
You have to join your tables and use case when to get the value which is not null:
select case when t1.size is null then t2.size else t1.size end as size,
case when t1.sizeorder is null then t2.sizeorder else t1.sizeorder end as sizeorder,
case when t1.color is null then t2.color else t1.color end as color
case when t1.colororder is null then t2.colororder else t1.colororder end as colororder
from <table> t1 join <table> t2 on t1.id = t2.id
I followed the instructions from This link
It seems that it doesn't improve much(only 0.09 Sec improved). Is not enough, My aim is to optimize it more.
Tables
state: id,title,abbr
regions: id,title
regions_suburbs: region_id,suburb_id
suburbs: id,state_id,region_id,postcode
properties: id,title
I am trying to find any keyword inside proprety.title, suburb.title, state.abbr, state.title and suburb.postcode.
Query as below-
[Perivous] Showing rows 0 - 4 (5 total, Query took 4.7122 sec)
SELECT * FROM (SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p LEFT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id UNION ALL SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p RIGHT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id UNION ALL SELECT CONCAT('state_id|',id),'' As SuburbName,'' AS postcode,abbr,title AS SearchTerm FROM state) AS U WHERE 1 AND (SuburbName LIKE 'Newtown%' OR postcode='Newtown' OR LOWER(SearchTerm) LIKE LOWER('Newtown%') OR abbr LIKE 'Newtown%') ORDER BY SearchTerm ASC LIMIT 0,10
EXPLAIN RESULT
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 16657 Using where; Using filesort
2 DERIVED p ALL NULL NULL NULL NULL 3
2 DERIVED s eq_ref PRIMARY PRIMARY 4 residential.p.suburb_id 1
2 DERIVED rs ALL NULL NULL NULL NULL 383
2 DERIVED r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
2 DERIVED st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1
3 UNION s ALL NULL NULL NULL NULL 16640
3 UNION p ALL NULL NULL NULL NULL 3
3 UNION rs ALL NULL NULL NULL NULL 383
3 UNION r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
3 UNION st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1
4 UNION state ALL NULL NULL NULL NULL 8
NULL UNION RESULT <union2,3,4> ALL NULL NULL NULL NULL NULL
[Now] Showing rows 0 - 4 (5 total, Query took 4.6246 sec)
SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p LEFT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id WHERE 1 AND (s.title LIKE 'Newtown%' OR postcode='Newtown' OR LOWER(CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END)) LIKE LOWER('Newtown%') OR st.abbr LIKE 'Newtown%') UNION ALL SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p RIGHT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id WHERE 1 AND (s.title LIKE 'Newtown%' OR postcode='Newtown' OR LOWER(CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END)) LIKE LOWER('Newtown%') OR st.abbr LIKE 'Newtown%') UNION ALL SELECT CONCAT('state_id|',id),'' As SuburbName,'' AS postcode,abbr,title AS SearchTerm FROM state WHERE 1 AND title LIKE 'Newtown%' ORDER BY SearchTerm ASC LIMIT 0,10
EXPLAIN RESULT
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY p ALL NULL NULL NULL NULL 3
1 PRIMARY s eq_ref PRIMARY PRIMARY 4 residential.p.suburb_id 1
1 PRIMARY rs ALL NULL NULL NULL NULL 383
1 PRIMARY r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
1 PRIMARY st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1 Using where
2 UNION s ALL title_postcode NULL NULL NULL 16640
2 UNION p ALL NULL NULL NULL NULL 3
2 UNION rs ALL NULL NULL NULL NULL 383
2 UNION r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
2 UNION st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1 Using where
3 UNION state range title title 102 NULL 1 Using where
NULL UNION RESULT <union1,2,3> ALL NULL NULL NULL NULL NULL Using filesort
Turn it inside out. Instead of computing everything you want and then seeing if 'Newtown%' is in each resulting piece, ...
For each table search the relevant fields for 'Newtown%'.
Join each of SELECT in Step 1 back to properties (assuming that is the focus of this dataset); get just properties's PRIMARY KEY.
UNION DISTINCT all of the SELECTs from Step 2.
Now JOIN to whatever tables are needed, and do the knarly CONCATs, etc to product the output -- based on the ids from Step 3.
Once you have done that, you can get some more performance if you are willing to use something other than SearchTerm in the ORDER BY. I would suggest simply properties.id. With that, you can do ORDER BYs in steps 2 and 3 to cut back on how much is shoveled from step to step.
(OFFSET will cause another issue when you have UNIONs; we can address that separately.)
Thank you all for your help here. I finally found the culprit that slown down my query.
I tried to remove bits by bits from my SQL statement and run it over and over. Finally after removing the following two LEFT JOIN parts,
LEFT JOIN regions_suburbs rs
ON rs.suburb_id = s.id
LEFT JOIN regions r
ON rs.region_id = r.id
it improves from
Showing rows 0 - 1 (2 total, Query took 4.8538 sec)
to
Showing rows 0 - 1 (2 total, Query took 0.2337 sec)
To acheive this I had to make some changes to databsae design. Initally, property table stores only suburb_id because we can get its region_id and state_id if we know suburb_id. To avoid joining regions_suburbs and regions table back, I am now storing state_id, region_id and suburb_id instead of only one suburb_id. In this we could take out two LEFT JOIN from the query and it improves the query response time tremendously by leveraging two additional column storage which is worth.
EDIT:
Creating some INDEX on the columns I am selecting grately improved the response time too.
Admittedly, I've seen this question on here a few times -- but all the answers seem to solve their problems by using a GROUP BY or a WHERE, so I was curious how to get around this if your query is getting too large where that wouldn't work.
For example, I'm writing something that uses two left joins to my main table, bringing the overlaps over into the results. As I'm still relatively new to SQL, I'm not exactly sure what's doing it -- but I know that I'm getting an extra thousand or so people when I run the counts; I'm imagining this is the case because there are duplicate IDs for each person (purposefully) in the two tables I'm joining.
All my queries populating the results I want to get for this project is using COUNT() or SUM() pending on the column. Is there a way that I can use DISTINCT to make only one column at a time treat my IDs only as one? Based on what I've done so far, I've noticed that whenever you set DISTINCT it works beyond just the one column you're trying to attribute it to. Any suggestions? It'd be very appreciated!
Here's an example of my code so far that includes duplicate IDs:
SELECT
targeted.person AS "Person",
targeted.work AS "Occu",
(COUNT(targeted.id)) AS "Targeted",
(COALESCE(SUM(targeted.signed="Yes"),0)) AS "Signed",
(COALESCE(SUM(targeted.signed="Yes"),0))/COUNT(targeted.id)*100 AS "Signed %",
(COALESCE(COUNT(question.questionid="96766"),0)) AS "Donated",
(COALESCE(COUNT(question.questionid="96766"),0))/(COALESCE(SUM(targeted.signed="Yes"),0))*100 AS "Donated %",
(COALESCE(SUM(question.surveyresponsename),0)) AS "Donation $",
ROUND((COALESCE(SUM(question.surveyresponsename),0))/(COALESCE(COUNT(question.questionid="96766"),0)),2) AS "Avg Donation",
(CASE WHEN (left(targeted.datesigned,1)="5" AND right(question.datecontacted,2)="13") THEN (COALESCE(SUM(targeted.signed="Yes"),0)) ELSE 0 END) AS "Signed This Month",
(CASE WHEN (left(question.datecontacted,1)="5" AND right(question.datecontacted,2)="13") THEN (COALESCE(COUNT(question.questionid="96766"),0)) ELSE 0 END) AS "Donated This Month",
(CASE WHEN question.ContactType="House Visit" THEN COUNT(question.id) ELSE 0 END) AS "At Home",
(CASE WHEN question.ContactType="Worksite" THEN COUNT(question.id) ELSE 0 END) AS "At Work",
(CASE WHEN (left(events.day,1)="5" AND right(events.day,2)="13") THEN COUNT(events.id) ELSE 0 END) AS "Events This Month"
FROM targeted
LEFT JOIN question ON targeted.id=question.id
LEFT JOIN events ON targeted.id=events.id
GROUP BY targeted.person, targeted.work;
Here are the basics of the table structures:
Targeted:
Field Type Null Key Default
ID bigint(11) YES Primary NO
Work varchar(255) YES NULL
Person varchar(255) YES NULL
Signed varchar(255) YES NULL
DateSigned varchar(255) YES NULL
Question:
Field Type Null Key Default
ID bigint(11) YES Primary NO
QuestionID int(11) YES NULL
SurveyResponseId int(11) YES NULL
SurveyResponseName varchar(255) YES NULL
DateContacted varchar(255) YES NULL
ContactType varchar(255) YES NULL
Events:
Field Type Null Key Default
ID bigint(11) NO Primary NO
Day varchar(255) YES NULL
EventType varchar(255) YES NULL
And the results would are intended to look something like:
Person Occu Targeted Signed Signed % ...
1 Job 1 1413 765 54.14 ...
2 Job 2 111 80 72.072 ...
2 Job 3 931 715 76.7991 ...
3 Job 4 2720 1435 52.7573 ...
4 Job 5 401 218 54.364 ...
Thanks for the help!
The proper way to solve this problem is by doing the aggregation in the subqueries. To aggregate questions and events to the right level, you need to join in the targeted table. Then, you will not need the aggregation at the outermost level:
select . . .
from (select t.name, t.work,
count(t.id) as Targeted,
. . .
from targets t
group by t.name, t.work
) t left join
(select t.name, t.work,
sum(case when question_id = 96766 then 1 else 0 end) as Donated,
. . .
from question q join
targeted t
on t.id = t.id
group by t.name, t.work
) q
on t.name = q.name and t.work = q.work left join
(select t.name, t.work,
sum(CASE WHEN (left(events.day,1)="5" AND right(events.day,2)="13") THEN 1 ELSE 0 END
) AS "Events This Month"
from events e join
targeted t
on e.id = t.id
) e
on e.name = t.name and e.work = t.work
I am having trouble with a mysql query. I want to exclude values of 2. So I thought I would do following:
table products
id | name | backorder
-------------------
1 | product1 | NULL
2 | product2 | NULL
3 | product3 | 2
SELECT name from `products` p
WHERE backorder <> '2'
However, This is not giving the desired result of product1, product 2 It is giving an empty results table.
On the other hand if I use
SELECT name from `products` p
WHERE backorder = '2'
Then it produces: product3. But I want to get those records where it is not equal to 2.
Something is not working with the <> '2'. Could it be that the NULL values are throwing it off? Can anyone suggest a fix.
Thanks in advance!
use IS NULL or IS NOT NULL to compare NULL values because they are simply unknown.
SELECT name
from products p
WHERE backorder IS NULL OR backorder <> 2
SQLFiddle Demo
SQLFiddle Demo (added some records)
Working with NULL Values
Use the <=> operator.
You can use:
SELECT `name` FROM `products` `p`
WHERE NOT `backorder` <=> '2'
or
SELECT `name` FROM `products` `p`
WHERE !(`backorder` <=> '2')
See this answer for more information about the <=> operator:
What is this operator <=> in MySQL?
Sorry to open this
We can use this also
SELECT name
from products p
WHERE COALESCE(backorder,1) <> 2
Try this and see.
SELECT name from `products` p
WHERE backorder != '2'