MySQL - Merge two join results - mysql

I need help with a raw SQL query which gets a value based on another value.
I have the following raw SQL query.
SELECT pmPropDef.id, pmPropDef.name, pmPropDef.units, pmPropShort.str, pmPropLong.str
FROM pmProp INNER JOIN pmPropDef ON pmProp.propid=pmPropDef.id AND pmPropDef.name = 'Area'
LEFT JOIN pmPropShort ON sid=pmProp.value
LEFT JOIN pmPropLong ON lid=-pmProp.value
WHERE pmProp.ownertype='variant' AND pmPropDef.id = pmProp.propid;
And this results in the following:
+----+------+-------+------+------+
| id | name | units | str | str |
+----+------+-------+------+------+
| 14 | Area | mm2 | 1.1 | NULL |
+----+------+-------+------+------+
The problem that I am getting both pmPropShort.str and pmPropLong.str and I should be betting one or the the other. What I really want is a single str value? How do I re-write this query to meet my needs?

You can use COALESCE which returns the first non-NULL argument. eg.
COALESCE(pmPropShort.str, pmPropLong.str)

Do you have an obvious priority?
example if long is priority
SELECT pmPropDef.id, pmPropDef.name, pmPropDef.units,
IF(pmPropLong.str IS NOT NULL,pmPropLong.str,pmPropShort.str) as str
FROM ...rest of your query

Related

MySQL: Concatenate two information, return a virtual column and in sequence perform an INNER JOIN with the column

In my project, I need make a Column with Concat information, like this:
CONCAT('SIP/', name) AS sipAgent.
And this works, but when i try to make a INNER JOIN with the column sipAgent, has error :(
And after inner join i need to SUM the results for each result of
like that:
----------------------------------
| NAME | sipAgent | notAnswered |
----------------------------------
| aaa | SIP/aaa | 132 |
| bbb | SIP/bbb | 50 |
----------------------------------
Name is the reference of agent, sipAgent is 'SIP/' + name, and noAnswered is the number of rows returned in a inner join.
Here is my 'test-query':
SELECT *, CONCAT('SIP/', tab_sippeers.name) AS sipAgent, SUM(queue_log.event) as notAnswered
FROM 'ipbx.tab_sippeers'
join 'queue_log' on tab_sippeers.sipAgent = queue_log.agent
But, is returning error...
Sorry for bad english, and thanks alot for help!
Query doesn't look right in other ways but you could concat in the join
SELECT *, CONCAT('SIP/', tab_sippeers.name) AS sipAgent, SUM(queue_log.event) as notAnswered
FROM `ipbx.tab_sippeers`
join `queue_log` on CONCAT('SIP/', tab_sippeers.name) = queue_log.agent;
and table names and column names should be enclose in backticks not single quotes if you want to enclose them at all.
When to use single quotes, double quotes, and back ticks in MySQL

2 inner joins between same 2 tables

I am trying to select columns from 2 tables,
The INNER JOIN conditions are $table1.idaction_url=$table2.idaction AND $table1.idaction_name=$table2.idaction.
However, From the query below, there is no output. It seems like the INNER JOIN can only take 1 condition. If I put AND to include both conditions as shown in the query below, there wont be any output. Please look at the picture below. Please advice.
$mysql=("SELECT conv(hex($table1.idvisitor), 16, 10) as visitorId,
$table1.server_time, $table1.idaction_url,
$table1.time_spent_ref_action,$table2.name,
$table2.type, $table1.idaction_name, $table2.idaction
FROM $table1
INNER JOIN $table2
ON $table1.idaction_url=$table2.idaction
AND $table1.idaction_name=$table2.idaction
WHERE conv(hex(idvisitor), 16, 10)='".$id."'
ORDER BY server_time DESC");
Short answer:
You need to use two separate inner joins, not only a single join.
E.g.
SELECT `actionurls`.`name` AS `actionUrl`, `actionnames`.`name` AS `actionName`
FROM `table1`
INNER JOIN `table2` AS `actionurls` ON `table1`.`idaction_url` = `actionurls`.`idaction`
INNER JOIN `table2` AS `actionnames` ON `table1`.`idaction_name` = `actionurls`.`idaction`
(Modify this query with any additional fields you want to select).
In depth: INNER JOIN, when done on a value unique to the second table (the table joined to the first in this operation) will only ever fetch one row. What you want to do is fetch data from the other table twice, into the same row, reading the select part of the statement.
INNER JOIN table2 ON [comparison] will, for each row selected from table1, grab any rows from table2 for which [comparison] is TRUE, then copy the row from table1 N times, where N is the amount of rows found in table2. If N = 0, then the row is skipped. In our case N=1 so INNER JOIN of idaction_name in table1 to idaction in table2 for example will allow you to select all the action names.
In order to get the action urls as well we have to INNER JOIN a second time. Now you can't join the same table twice normally, as SQL won't know which of the two joined tables is meant when you type table2.name in the first part of your query. This would be ambiguous if both had the same name. There's a solution for this, table aliases.
The output (of my answer above) is going to be something like:
+-----+------------------------+-------------------------+
| Row | actionUrl | actionName |
+-----+------------------------+-------------------------+
| 1 | unx.co.jp/ | UNIX | Kumamoto Home |
| 2 | unx.co.jp/profile.html | UNIX | Kumamoto Profile |
| ... | ... | ... |
+-----+------------------------+-------------------------+
While if you used only a single join, you would get this kind of output (using OR):
+-----+-------------------------+
| Row | actionUrl |
+-----+-------------------------+
| 1 | unx.co.jp/ |
| 2 | UNIX | Kumamoto Home |
| 3 | unx.co.jp/profile.html |
| 4 | UNIX | Kumamoto Profile |
| ... | ... |
+-----+-------------------------+
Using AND and a single join, you only get output if idaction_name == idaction_url is TRUE. This is not the case, so there's no output.
If you want to know more about how to use JOINS, consult the manual about them.
Sidenote
Also, I can't help but notice you're using variables (e.g. $table1) that store the names of the tables. Do you make sure that those values do not contain user input? And, if they do, do you at least whitelist a list of tables that users can access? You may have some security issues with this.
INNER JOIN does not put any restriction on number of conditions it can have.
The zero resultant rows means, there is no rows satisfying the two conditions simultaneously.
Make sure you are joining using correct columns. Try going step by step to identify from where the data is lost

MySQL query - how to look for certain string in the field

I have a table "story" as follows:
+++++++++++++++++++++++++++++++++++++++++++
| id | keywords |
+++++++++++++++++++++++++++++++++++++++++++
| 1 | romance,movie,drama |
| 2 | newmovie,horor,comedy |
| 3 | movie,scifi |
| 4 | newmovie,romance,drama,asia |
| 5 | kids,movie |
+++++++++++++++++++++++++++++++++++++++++++
I try a query to search 'movie' in keywords field as below:
SELECT id FROM story WHERE keywords LIKE '%movie%'
and the result is
1,2,3,4,5
but in this case I wanted the result is 1,3,5 (field value with newmovie not include). Can someone help me how the query to do it?
Thank you for your help..
You want to use find_in_set like this:
SELECT id FROM story WHERE find_in_set('movie', keywords) > 0;
Though you should really consider normalizing your table structure.
In this case, you could've stored one single keyword in one row, then the query would be simply like:
select id from story where keyword = 'movie';
and that would've been the end of it. No heavy string functions needed.
You could have structure like this:
keywords(id, name);
story(story_id,. . ., keyword_id);
then, you could simply join the two like this:
select s.*
from story s
inner join keywords k on s.keyword_id = k.id
where k.name = 'movie';
Your problem is that "newmovie" can be found by "%movie%" you need only search "movie".

Using GROUP_CONCAT in separate row records

I'm having trouble using GROUP_CONCAT. I'm pretty sure this is the only way to get what I want but it doesn't seem give me the results I need.
Here is my statement:
SELECT
b.*,
GROUP_CONCAT(c.finance_code) AS finance_codes
FROM
`oc_finance_breakpoints` b
LEFT JOIN
`oc_finance_breakpoints_codes` c ON c.breakpoint_id = b.breakpoint_id;
This will gather data in the finance_breakpoints table, structure below:
breakpoint_id
from_value
to_value
minimum_deposit
As well as multiple "finance codes" from my join table, finance_breakpoint_codes:
breakpoint_code_id
breakpoint_id
finance_code
There can be, are are likely to be, several finance codes to a breakpoint. When I run the sql when there is only one entry, I get the following:
1 | 280.00 | 750.00 | 10 | ONIF6,ONIF10,ONIF12
But if there are two entries in the breakpoints table, all that happens is it tacks the additional finance codes onto the end of the above, meaning I only ever get one row with the first set of data, and all the finance codes in one column.
Ideally I'd like it to return something such as this:
1 | 280.00 | 750.00 | 10 | ONIF6,ONIF10,ONIF12
2 | 750.00 | 1500.00 | 10 | ONIB12-9.9,ONIB24-9.9,ONIB36-9
Rather than:
1 | 280.00 | 750.00 | 10 | ONIF6,ONIF10,ONIF12,ONIB12-9.9,ONIB24-9.9,ONIB36-9
Is there any way of achieving what I want? Am I maybe using the wrong function?
The use of an aggregate function (such as GROUP_CONCAT) in your query ensures that it will return aggregated results, while the absence of an explicit grouping ensures that it will return a single, overall summary row.
You need to add a group by clause to the end of your query - like so:
SELECT
b.*,
GROUP_CONCAT(c.finance_code) AS finance_codes
FROM
`oc_finance_breakpoints` b
LEFT JOIN `oc_finance_breakpoints_codes` c
ON c.breakpoint_id = b.breakpoint_id
GROUP BY b.breakpoint_id

MySQL SELECT row if next row is different value?

I've Googled a lot but I can't quite figure this out. I apologize if this is a trivial question.
I would like to SELECT a row if the 'batter' column equals a certain value AND the next row is not the same batter. I'm trying to get the row that represents the final pitch of the at bat. If it is the final pitch, then the next row would be a new batter. I'm using an auto-incremented id column if that helps.
EDIT:
Here's how the data is organized.
Right now if I want to know how many times batter "276055" struck out I would do:
SELECT * FROM `mlb2012` WHERE batter = "276055" AND atbat_event = "strikeout" AND atbat_pitch = "1"
But if I want to know how many times he struck out looking, I would need to know the pitch_des of the last pitch of the atbat.
ID | Batter | atbat_pitch | atbat_event | pitch_des |
----------------------------------------------------------
1 | 457477 | 1 | Double | Called Strike
2 | 457477 | 2 | Double | In play, no out
3 | 452121 | 1 | Strikeout | Foul
4 | 452121 | 2 | Strikeout | Foul
5 | 452121 | 3 | Strikeout | Called Strike
6 | 543569 | 1 | Walk | Ball
Pseduo code (90% likely to work):
set #last_batter_id = NULL;
select batter_id, #last_batter_id,
case when batter = "certain value" and batter_id != #last_batter_id then 'use me' else 'skip me' end as my_action,
#last_batter_id := batter_id
from my_table
If you want just the batters that you want to use, wrap the last query:
select *
from (
[ query from above ]
) foo
where foo.my_action = 'use me'
Intriguing question.
Looks like you want to join that table to itself based on the rowid on the current row joining the rowid on the previous and checking the 'batter' field is not equal. Use left outer join to handle the last row (ie will return if there is no subsequent row to be joined to). Dont' know mysql syntax but try something like:
SELECT fr.*
FROM mytable fr
LEFT OUTER JOIN mytable nr
ON fr.#rowid = nr.#rowid+1
WHERE fr.batter <> nr.batter
(you can replace the left outer join and on clauses with where conditions and += arguments - I assume you've got the basic MySQL syntax down).