I'm new to SQL.
Problem: Say if I were to count the amount that is contained in the alias table of "x" COUNT(x.xValue) to be 217. Now when I add the sub-query "y" and then do the count again, I have the COUNT(x.xValue) to suddenly square its self -> 47089. Why is this happening?
(Note: Both alias tables "x" and "y" have the same amount -> 217.)
How do I fix this problem. I don't want to use Variables or Views.
SELECT COUNT(x.xValue) + COUNT(y.yValue) AS CountXY
FROM
(SELECT value AS xValue FROM table1
WHERE
...) AS x,
(SELECT value AS yValue FROM table1
WHERE
...) AS y
Result of 'CountXY' : 94178.
Result I'm expecting 'CountXY' : 434
The problem is that you are doing two sub-queries and then trying to call the values return directly.
This will behave as selecting one value from table x and matching it to every single value in table y. This obviously creates the squared return effect.
What you need to use is the JOIN to combine both data-sets so that you get the 1 to 1 relationship you are trying to achieve.
This is how the above should be done with your previous sub-query:
SELECT COUNT(A.value) AS x, COUNT(B.value) AS y
FROM table1 AS A
JOIN table1 AS B
ON A.attr1 = B.attr1
AND A.attr2 = B.attr2
WHERE B.attr1 != 'whatever'
AND B.attr2 = 'whatever'
AND A.attr3 = 'something'
AND B.attr3 = 'something different'
The above query should return the correct 1 to 1 relationship you are looking for. Replacing your sub-query with the one above should give you the correct answer
Related
I am trying to write a query that selects values from certain rows based on their parameters, then does some calculations and returns the result. I also need to update the rows that were selected. I can only think of ways to do both of these actions with separate queries, but is there a way to do both at once?
Example queries would be:
SELECT SUM(a.val1*b.val1)
FROM a, b
WHERE a.val2 = condition1 AND b.val2 = condition2;
UPDATE a
SET a.val3 = a.val1*b.val1
FROM a INNER JOIN b ON a.val2 = condition1 AND b.val2 = condition2;
Is there a way to combine them?
No. There is no syntax in SQL that allows you to retrieve values and update them in the same query. Use SELECT to retrieve values and UPDATE to change them.
You can use SELECT inside an UPDATE statement as part of the calucalation, but the result will not be the values of what has been updated, only the number of rows that were updated.
Your SELECT statement has a small mistake in it and should be as follows:
SELECT SUM(a.val1*b.val1) FROM a, b WHERE a.val2 = 1 and b.val2 = 1;
This only returns one row: the sum of the product of val1 columns in tables a and b where the val2 columns meet certain conditions.
It is not clear what you are trying to achieve by updating table a with the result of this. If you are looking to set val3 in table a with the product of val1 in tables a and b if the val2 in those tables meet certain criteria, the following might work, but you need to add a join between columns in both tables otherwise val3 will be set to the product of val1 in table a and all the val1 values in table b, which may not be what you want.
UPDATE a
SET a.val3 =
(
SELECT a.val1*b.val1
FROM b
WHERE b.key = a.key
AND b.val2 = condition2
)
WHERE a.val2 = condition1;
Nope :)
In SQL it is always different queries. You can write a function that will do 2 actions, but never one query.
This will have to be done in two steps - Select and Aggregate then Update.
I made a mysql query that is getting a result set from table A using a value 'x' stored in table B. Right now whenever I need 'x' I need to reSELECT it up to 6 times.
Simplified version of my query looks something like this:
SELECT * FROM A WHERE a = (SELECT x FROM B ...) AND b = (SELECT x FROM B ...)-5 AND c = (SELECT x FROM B ...)+7
Is there a way to store that value 'x' during the evaluation of my sql statement?
If not, does it make sense to use 2 queries instead (first one to get 'x' and second one with 'x' included in the real statement)?
If you want to see one of my statements, here is an example:
"(SELECT * FROM map WHERE x BETWEEN :x-:sight and :x+:sight AND y BETWEEN :y-:sight+:map_max_y and :map_max_y) /*1.part*/
UNION
(SELECT * FROM map WHERE x BETWEEN :map_min_x and MOD((:x+:sight),:map_max_x) AND y BETWEEN :y-:sight+:map_max_y and :map_max_y ORDER BY y LIMIT 225) /*2.part*/
UNION
(SELECT * FROM map WHERE x BETWEEN :x-:sight and :map_max_x AND y BETWEEN :map_min_y and :y+:sight ORDER BY y LIMIT 225) /*3.part*/
UNION
(SELECT * FROM map WHERE x BETWEEN :map_min_x and MOD((:x+:sight),:map_max_x) AND y BETWEEN :map_min_y and :y+:sight ORDER BY y LIMIT 225) /*4.part*/";
'x', 'y', 'sight' are all stored in the DB and it hurts my eyes to reload them that many times (this is the older version which doesn't load them from DB just yet). And I believe making 2 queries is a bad habit aswell.
Thank you in advance, guys :)
Mysql optimizer should be able to detect such duplicated subselect and perform it only once. Just make sure it is really the same select which does not use anything variable from outside, and use EXPLAIN to confirm, that it gets optimized.
Lets say I have a table, myTable, like this:
ID1 Value ID2
1 6.5064 3
2 7.9000 3
3 9.9390 3
4 8.6585 3
What I'm trying to do is SELECT each of those Value's for a given ID2. However, the number of rows returned for Value can change. So, if ID2 = 2, only 1 row might get returned. If drID = 4, 3 rows might get returned.
The part of my query that is trying to handle this is nested, so when I run it I get a "Subquery returns more than 1 row" error. Any idea how I can select a variable number of rows in this way?
Thanks in advance!
Edit: here is what I have so far, and the commented out portion is what I expected to select those values for me, but it throws the above mentioned error:
SELECT drDateTime AS Date,
(SELECT fncName FROM functionlist
WHERE datarecord.fncID = functionlist.fncID) AS FunctionName,
(SELECT alText FROM alarmlevellist
WHERE datarecord.alID = alarmlevellist.alID) AS AlarmDescription
#(SELECT rdValue FROM rawdata
#WHERE datarecord.drID = rawdata.drID)
FROM datarecord
WHERE alID IS NOT NULL AND drSumFlag = 1;
You should show your query.
One common place this problem occurs is in where (or having) clauses. A solution to this problem is to use in rather than =, if the subquery is in the where clause. If you have something like:
where id = (select id2 . . .)
Then change it to:
where id in (select id2 . . .)
Use a join instead of a subquery. I would probably use a join for all tables but that is up to you.
SELECT drDateTime AS Date,
(SELECT fncName FROM functionlist WHERE datarecord.fncID = functionlist.fncID) AS FunctionName,
(SELECT alText FROM alarmlevellist WHERE datarecord.alID = alarmlevellist.alID) AS AlarmDescription,
rawData.drID
FROM datarecord
INNER JOIN rawdata
ON datarecord.drID = rawdata.drID)
WHERE alID IS NOT NULL AND drSumFlag = 1;
This is basically the structure of my query:
SELECT * FROM foo WHERE foo1 = (subquery here)
I want to detect when the subquery doesn't return any rows, and then use another value as a placeholder.
How can I do that?
you can use left join, it will work :
SELECT * FROM table AS t1
left join
table as t2
on t1.Target = t2.Target
and t2.phase="B"
where t2.target is null OR
OR t1.date < t2.Date
you can replace your conditions here by changing null ans your conditions here.
By doing a left join you are including all rows on the left side of the join, and only matching rows from the right side of the join. Assuming a left side table t1, and right side table t2, in cases where the join condition is not met the value of any column in t2 will be be null. Since the goal in this case is to omit the where clause if our join condition is not met (targets match and the t2 phase value is 'B') we first check to see if the join condition failed, if so we return a row.
Got the answer!
SELECT * FROM foo WHERE foo1 = IF((subquery with count parameter as replacement), placeholder, (subquery))
Try your subquery alone , then use this:
mysql_num_rows to know how many rows has been affected by your subquery, if the number is 0 then create a query with another place holder
note
rowCount() to know the number of rows using PDO
you can just pass this by a condition above, like count your fetched data using using mysql_num_rwos , and assign that value to a variable and then put it in if else loop for conditions like as :
$a = mysql_num_rows(query);
if($a == '')
{
$a = your placeholder here;
}
SELECT * FROM foo WHERE foo1 ='".$a."'
something like that.
I want to write mysql when statement and i can't do it.
explanation => localParty is column in table "data", loc is column from table "o", and i want to compare localParty to loc, if their values are equal then i want to retrieve information from loc_m column (this column is from table "o"), and if not equal then from localParty column (from "data" table)
Please help how to write this script in mysql query ? Thanks
with this script
select (case when data.localparty = o.loc then o.loc_m else data.localparty end)
as customdata from data, o
it is working but it is missing exactly three result ( I mean that then data.localparty equal to o.loca it is giving result from data.localparty 3 times and after it one time it is giving result from loc_m and it is going like so .
You could modify the query in the following way:
SELECT IF(t1.Column1 = t2.Column2,t2.Column1,t1.Column3) FROM TABLE1 AS t1, Table2 AS t2
Try This:
select (case when data.localparty = o.loc then o.loc_m else data.localparty end)
as customdata from data, o
you can use following query
Select O.loc_m as local
from Data
inner join on O on data.localparty=O.loc
UNION
Select data.loacalparty as local
from Data
where data.localparty is not in (select loc from O )
You should use control-flow functions to achieve that goal:
SELECT IF(Column1 = Column2,Column1,Column3) FROM TABLE1