mysql count problems - mysql

SELECT count( t1.id ) , t2.special_value
FROM table_1 AS t1, table_2 AS t2
WHERE t1.`group` = 'val'
AND t2.code = 'val'
returns
count - normal value
special_value - NULL
but
SELECT t2.special_value
FROM table_2 AS t2
WHERE t2.code = 'val'
returns
special_value - another normal value
why first query works wrong?..
currently, i need
(count( t1.id ) + t2.special_value)

This is why you should never use SQL'89 implicit join syntax.
You have no join condition resulting in a cross join.
Rewrite the query using explicit join syntax:
SELECT count( t1.id ) , t2.special_value
FROM table_1 AS t1
INNER JOIN table_2 AS t2 ON (t1.`group` = t2.code) <<-- join condition here
WHERE .... <<-- filter condition here
GROUP BY .... <<-- group by field here
I don't know how table t1 and t2 are linked, so you'll have to tweak this a bit, but that's how it supposed to work.
And please never ever use implicit where joins again.
Remarks
I'm wondering what p.`group` and pp.code are, but I'm guessing you meant to write t1.`group` and t2.code
You only need to escape fields and tablenames in ` backticks if they are reserved words.
Personally all those backticks make me dizzy, but that's just me.

Related

Issue with SQL join query

this is a simplified version of my query. It runs in SQLite without an issue, but not so in MYSQL.
Error: Unknown column 'tab2.key' in 'on clause'
SELECT
tab2.key AS remarksId,
tab1.sessionDate AS date,
tab1.sessionStart AS startTime
FROM
table1 AS tab1,
table2 AS tab2,
table3 AS tab3,
table4 AS tab4
INNER JOIN
table5 AS tab5
ON
tab5.remarkId = tab2.key
WHERE
tab1.userId='<anyNumber>' AND
tab2.objectiveId='<anyKey>' AND
tab1.reportId=tab2.reportId AND
tab1.reportId=tab3.key AND
tab4.key=tab3.sortieId
ORDER BY date, startTime;
To put the columns in ` unfortunately was no help.
I'm not sure if naming a column 'key' is a good practice (MYSQL Keywords), but I have to handle this somehow, due to existing installations. For a quick test, I renamed the 'key'-columns, but also without any success.
Thanks a lot
Simply put, Don't mix join notations, and if given the choice use the current ANSI 92 join syntax instead of the 89 standard (yes... that's 1992 and 1989!)
Secondly... aliases are to help you save typing and handle multiple references to the same table.... so... simplify the names t1, t2, t3...
Lastly... if you have to use reserved/restricted words in mySQL use backticks.
SELECT t2.`key` AS remarksId
FROM table1 t1
INNER JOIN table2 t2
ON t1.reportId = t2.reportId
INNER JOIN table3 t3
ON t1.reportId = t3.`key`
INNER JOIN table4 t4
ON t4.`key` = t3.sortieId
INNER JOIN table5 t5
ON t5.remarkId = t2.`key`
WHERE t1.userId = '<anyNumber>'
AND t2.objectiveId = '<anyKey>'
ORDER BY `date`, startTime;

Sum the same value with different condition

Ok, the title is cryptic but I don't know how to sintetize it better.
I have a series of expensive similar SELECT SUM queries that must be executed in sequence.
Example:
SELECT SUM(t2.Field)
FROM Table1 AS t1
INNER JOIN (
SELECT Field FROM Table2
WHERE [list of where]
) AS t2 ON ti.ExtKey = t2.Key
WHERE t1.TheValue = 'Orange'
SELECT SUM(t2.Field)
FROM Table1 AS t1
INNER JOIN (
SELECT Field FROM Table2
WHERE [list of where]
) AS t2 ON ti.ExtKey = t2.Key
WHERE t1.TheValue = 'Apple'
And so on.
I've used the nested inner join because after some test it resulted faster than a plain Join.
The rows selected for Table2 are always the same, or at least the same for session.
There's a way to group all the queries in one to speed up the execution?
I was thinking about using a material view, but this would complicate very much the design and maintenance.
I am no sure about your goal. I have a guess for you:
http://sqlfiddle.com/#!9/af66e/2
http://sqlfiddle.com/#!9/af66e/1
SELECT
SUM(IF(t1.TheValue = 'Orange',t2.Field,0)) as oranges,
SUM(IF(t1.TheValue = 'Apple',t2.Field,0)) as apples
FROM Table1 AS t1
INNER JOIN (
SELECT Field, `key` FROM Table2
) AS t2 ON t1.ExtKey = t2.`key`
# GROUP BY t1.extkey uncomment if you need it
If you can provide raw data sample and expected result that would help a lot.
I think you want a group by:
SELECT t1.TheValue, SUM(t2.Field)
FROM Table1 t1 INNER JOIN
(SELECT Field
FROM Table2
WHERE [list of where]
) t2
ON t1.ExtKey = t2.Key
GROUP BY t1.theValue;
Note that your query doesn't quite make sense, because t2 doesn't have a column called key. I assume this is an oversight in the question.
If you want to limit it to particular values, then use a WHERE clause before the GROUP BY:
WHERE t1.TheValue IN ('Apple', 'Orange', 'Pear')

Merge two queries and return one of the possible values

select value1 as value from T1 where id=10;
if id does not exist in T1 - execute another query:
select value2 as value from T2 where id=10;
So, I want to join these queries and return a single value (value1 or value2). Is it possible?
SOLUTION:
My solution:
select ifnull(value1, value2) as value from T1 left join T2 using(id) where id=10;
you can join the query using union
select value1 as value from T1 where id=10
union
select value2 as value from T2 where id=10;
as a result you can get any one of the value or both
TRY (tested)
SELECT COALESCE(t1.value1, t2.value2) AS Value FROM t1
INNER JOIN t2 USING(id)
WHERE id=10
this will always check first the table t1 for id=10, if there is no value then see table t2 for the same id
Quoted FROM
The single result column that replaces two common columns is defined
using the coalesce operation. That is, for two t1.a and t2.a the
resulting single join column a is defined as a = COALESCE(t1.a, t2.a)
You can join the two queries on the id field and then use the COALESCE function to combine the two resulting fields into the output.
This assumes that you already have a list of IDs to join against, though. Otherwise you're stuck doing a union or full join to get such a list first.
You Can use this too
select Distinct(s1.id) from sample1 as s1 inner join sample2 as s2;
use union of both
like below :
select t1.id from table1 as t1 where id=10
union
select t2.id from table2 as t2 where id=10

SQL query to get only the latest value by Date

I have the following two tables:
Table1 {T1ID, Name}
Table2 {T2ID, T1ID, Date, Value}
Date is of type DATE.
and I am looking for a SQL query to fetch only the latest value (by Date) for each T1ID for which the Name matches a specific string.
SELECT`Table2`.`T1ID`,
`Table2`.`Value`,
`Table2`.`Date`,
`Table1`.`Name`,
FROM `Table1`
INNER JOIN `Table2` ON `Table2`.`T1ID` = `Table1`.`T1ID`
WHERE `Table1`.`Name` LIKE 'Smith'
but this returns the value for several dates for the same T1ID.
How do I get only the latest value by Date?
Edit:
I am using MySQL 5.5.8
If I've understodd the question correctly:
Assuming MySQL:
SELECT`Table2`.`T1ID`,
`Table2`.`Value`,
`Table2`.`Date`,
`Table1`.`Name`
FROM `Table1`
INNER JOIN `Table2` ON `Table2`.`T1ID` = `Table1`.`ID`,
(SELECT T1ID, MAX(Date) AS 'Date' FROM Table2 GROUP BY T1ID) Table3
WHERE
`Table3`.`T1ID` = `Table2`.`T1ID`
AND
`Table3`.`Date` = `Table2`.`Date`
AND
`Table1`.`Name` LIKE 'Smith'
EDIT: Updated the code to bring back the correct result set. Removed MSSQL answer as it wasn't relevant
You have two options.
select t1.t1id, max(t1.Name) Name, max(t2.date) Date,
(select Value from table2 t22
where t22.date = max(t2.date) and t22.t1id = t2.t1id) Value
from table1 t1 left join table2 t2 on t1.t1id = t2.t1id
where Name like '%Smith%'
group by t2.t1id order by 2
OR
select mx.t1id, mx.Name, mx.Date, t2.Value
from
(
select t1.t1id, max(t1.Name) Name, max(t2.date) Date
from table1 t1 left join table2 t2 on t1.t1id = t2.t1id
where Name like '%Smith%'
group by t2.t1id
) mx left join table2 t2 on (t2.t1id = mx.t1id and t2.date = mx.date)
order by 2
Both will produce the same result. The first one takes less code but you might have performance issues with a huge set of data. The second one takes a little more code, but it is also a little more optimized. Notes on the JOIN option:
If you go LEFT JOIN (as the example shows), items in Table1 with no correspondent records on Table2 will be displayed in the result, but the values in columns Date and Value will be NULL
If you go INNER JOIN, items in Table1 with no correspondent records on Table2 will not be displayed.
EDIT
I missed one of the requirements, which was the Name matching a specific string. The code is now updated. The '%' acts like a wildcard, so it will match names like 'Will Smith' and 'Wail Smithers'. If you want a exact match, remove the wildcards ('%').
Add this to your SQL:
ORDER BY 'Date' DESC LIMIT 1

Subquery error in MySQL with max()

I'm trying a subquery in MySQL using max(), and I keep running into an error. The gist of the query is below (though I've changed the field names).
select table1.field1, table1.field2, table2.field3, table2.field4, table3.field5,
(select max(age)
from age_table
where age_table.person = table2.person)
from table1
inner join table2 on table2.person = table1.person
inner join table3 on table3.person = table1.person
inner join age_table on age_table.person = table1.person
When I try this, I get a syntax error that points to
'from age_table where age_table.person=table2.person'
...but I can't figure out what the problem is.
Use table aliases to differentiate between tables, without having to use the full table name:
SELECT t1.field1, t1.field2, t2.field3, t2.field4, t3.field5,
(SELECT MAX(at.age)
FROM AGE_TABLE at
WHERE at.person = t2.person) AS max_age
FROM TABLE1 t1
JOIN TABLE2 t2 ON t2.person = t1.person
JOIN TABLE3 t3 ON t3.person = t1.person
I removed what appeared to be a redundant JOIN to the AGE_TABLE, seeing as it wasn't used in the SELECT clause.
It's also good habit to define a column alias for derived column values - makes them easier to reference. See "max_age" for an example.
You need to create an alias for your subquery eg:
(select max(age) from age_table where age_table.person = table2.person) temp
and leave rest of the things as they are.