Could anyone point me in the correct direction on how to do this SQL query? I have two tables coord_table and rm_table. I would like to perform a query where any coord_table.loc which falls between any rm_table.start_loc or rm_table.end_loc is removed from the result of the query.
coord_table
coord_id loc
____________________
1 9
2 19
3 30
4 55
rm_table
rast_id start_loc end_loc
___________________________
1 10 20
2 50 60
query_result
coord_id loc
_____________
1 9
3 30
EDIT: This should work. It uses the BETWEEN syntax:
SELECT a.* FROM coords_table a
LEFT JOIN
(
SELECT
*
FROM
(
SELECT
coords_id, loc, start_loc, end_loc,
(loc BETWEEN start_loc AND end_loc) as is_between
FROM
coords_table, rm_table
) a
WHERE a.is_between = 1
) b
ON a.coords_id = b.coords_id
WHERE b.coords_id IS NULL
Fiddle: http://sqlfiddle.com/#!9/3acdb/2
Related
Currently I am honestly at loss what I am doing wrong. It is a rather simple query I think.
Tables:
operations:
id processedon clientid
1 2018-01-01 9
2 2018-03-16 9
3 2018-04-21 9
4 2018-04-20 9
5 2018-05-09 9
items:
id operation_id quantity unitprice
1 1 10 2
2 1 5 3
3 2 20 4
4 3 10 2
5 4 8 4
6 4 10 4
7 5 2 2
The expected result of the operation/query is:
month total_value
1 35
3 80
4 92
5 4
That is quantity * unitprice based. For some reason, it only returns month=4
SELECT
month(`operations`.`processedon`) AS `month`,
SUM((`items`.`quantity` * `items`.`unitprice`)) AS `total_value`
FROM `items`
INNER JOIN `operations` ON (`items`.`operation_id` = `operations`.`id`)
GROUP BY 'month'
ORDER BY 'month'
According to the info provided the join should be
INNER JOIN operations ON items.operation_id = operations.id
Eg
SELECT
month(`operations`.`processedon`) AS `month`,
SUM((`items`.`quantity` * `items`.`unitprice`)) AS `total_value`
FROM `items`
INNER JOIN `operations` ON `items`.`operation_id` = `operations`.`id`
GROUP BY month(`operations`.`processedon`)
ORDER BY `month`
There is no efficiency gain by using a column alias in the group by clause, I prefer to avoid using them except perhaps in the order by clause.
The following query will give you the required answer
SELECT
month(`operations`.`processedon`) AS `month`,
SUM((`items`.`quantity` * `items`.`unitprice`)) AS `total_value`
FROM items
INNER JOIN operations ON (items.operation_id = operations.id)
GROUP BY month(operations.processedon)
ORDER BY month(operations.processedon)
You need to specify month correctly since it is not an existing column.
You'll get the following result
month total_value
1 35
3 80
4 92
5 4
I want to write a mysql query to fetch distinct product_id where combination of attribute_id column for the similar product_id values to be displayed.
I tried this one:
SELECT DISTINCT(product_id) FROM oc_product_attribute WHERE (attribute_id = 26 AND CAST(text AS UNSIGNED) >= '1') and (attribute_id = 29 AND text = 'Flange')
product_id attribute_id language_id text
1 12 1 0.25 - 20
1 13 1 2500
1 14 1 30
1 15 1 130-160
1 16 1 1.00
1 17 1 0.50
1 18 1 Medium accuracy
1 19 1 PC mountable
1 20 1 N/A
2 21 1 50
2 22 1 +/- +/-100
2 23 1 +5
2 24 1 2.5 v to +/-0.625
2 25 1 DC to 20
2 26 1 1.00
2 27 1 < 1 % of FS
2 28 1 4 PIN Connector
2 29 1 Flange
2 30 1 N/A
So basically what i want is, a query should be run on different rows of similar product_id column where logical operator with concatenation and logical operators.
Please let me know, if the question is not clear.
You need to do EXISTS()...
SELECT DISTINCT product_id
FROM oc_product_attribute t1
WHERE EXISTS(SELECT * FROM oc_product_attribute t2
WHERE t1.product_id=t2.product_id
AND attribute_id = 26 AND CAST(text AS UNSIGNED) >= '1'
)
AND EXISTS (SELECT * FROM oc_product_attribute t3
WHERE t1.product_id=t3.product_id
AND attribute_id = 29 AND text = 'Flange')
If you need to test for more attribute/text combinations, just add another EXISTS() clause for each one.
You can use a subquery along with the IN operator to solve this. Think of it this way.
First, write a query that pulls all product_ids that match the first requirement:
SELECT DISTINCT product_id
FROM oc_product_attribute
WHERE (attribute_id = 26 AND CAST(text AS UNSIGNED) >= '1');
Then, write a second query that pulls all product_ids that match the first requirement:
SELECT DISTINCT product_id
FROM oc_product_attribute
WHERE (attribute_id = 29 AND text = 'Flange');
Now, you can write your final query with the idea that you want to select all rows from the first result set whose product_id value is also in the results of the second set. Try this:
SELECT DISTINCT product_id
FROM oc_product_attribute
WHERE (attribute_id = 26 AND CAST(text AS UNSIGNED) >= '1') AND product_id IN(
SELECT DISTINCT product_id
FROM oc_product_attribute
WHERE (attribute_id = 29 AND text = 'Flange'));
You can try this:
select distinct p_id from (SELECT DISTINCT(product_id) as p_id FROM oc_product_attribute WHERE (attribute_id = 26 AND CAST(text AS UNSIGNED) >= '1') or (attribute_id = 29 AND text = 'Flange'))
In MySql I need to select top student in every class in a school in termid=10 to get discount for next term enrollment .
Please notice that total is not in table(I put in below for clearing problem)
I have this workbook table for all students workbook:
id studentid classid exam1 exam2 total termid
1 2 11 20 40 60 10
2 1 22 40 20 60 10
3 4 11 40 20 60 10
4 5 33 10 60 70 10
5 7 22 10 40 50 10
6 8 11 10 30 40 10
7 9 33 20 45 65 10
8 11 11 null null null 10
9 12 54 null null null 02
10 13 58 null null null 02
1st challenge is : exam1 and exam2 are VARCHAR and total is not in table (as i explained).
2nd challenge is : as you can see in id=8 std #11 has not numbers
3rd challenge is : may be two students have top level so they must be in result.
I need result as :
id studentid classid exam1 exam2 total termid
1 2 11 20 40 60 10
3 4 11 40 20 60 10
4 5 33 10 60 70 10
2 1 22 40 20 60 10
i have this query but not work good as i mention.
SELECT DISTINCT id,studentid,classid,exam1,exam2,total,termid ,(CAST(exam1 AS DECIMAL(9,2))+CAST(exam2 AS DECIMAL(9,2))) FROM workbook WHERE ClassId = '10';
You can get the total for the students by just adding the values (MySQL will convert the values to numbers). The following gets the max total for each class:
select w.classid, max(coalesce(w.exam1, 0) + coalesce(w.exam2, 0)) as maxtotal
from workbook w
group by w.classid;
You can then join this back to the original data to get information about the best students:
select w.*, coalesce(w.exam1, 0) + coalesce(w.exam2, 0) as total
from workbook w join
(select w.classid, max(coalesce(w.exam1, 0) + coalesce(w.exam2, 0)) as maxtotal
from workbook w
group by w.classid
) ww
on w.classid = ww.classid and (coalesce(w.exam1, 0) + coalesce(w.exam2, 0)) = ww.maxtotal;
Another approach is to join the table with itself. You find out the max for each class and then join all students of this class which match the class max:
max for each class (included in the final statement already):
SELECT classid, MAX(CAST(exam1 AS UNSIGNED) + CAST(exam2 AS UNSIGNED)) as 'maxtotal'
FROM students
WHERE NOT ISNULL(exam1)
AND NOT ISNULL(exam2)
GROUP BY classid
The complete statement:
SELECT s2.*, s1.maxtotal
FROM (SELECT classid, MAX(CAST(exam1 AS UNSIGNED) + CAST(exam2 AS UNSIGNED)) as 'maxtotal'
FROM students
WHERE NOT ISNULL(exam1)
AND NOT ISNULL(exam2)
GROUP BY classid) s1
JOIN students s2 ON s1.classid = s2.classid
WHERE s1.maxtotal = (CAST(s2.exam1 AS UNSIGNED) + CAST(s2.exam2 AS UNSIGNED));
SQL Fiddle: http://sqlfiddle.com/#!2/9f117/1
Use a simple Group by Statement:
SELECT
studentid,
classid,
max(coalesce(exam1,0)) as max_exam_1,
max(coalesce(exam2,0)) as max_exam_2,
sum(coalesce(exam1,0) + coalesce(exam2,0)) as sum_exam_total,
termid
FROM
workbook
WHERE
termid=10
GROUP BY
1,2
ORDER BY
5
Try something like this:
SELECT id,studentid,classid,exam1,exam2,(CAST(exam1 AS DECIMAL(9,2))+CAST(exam2 AS DECIMAL(9,2))) AS total,termid FROM `workbook` WHERE ((CAST(exam1 AS DECIMAL(9,2))+CAST(exam2 AS DECIMAL(9,2)))) > 50
Thanks all my friends
I think combine between 2 answer in above is best :
SELECT s2.*, s1.maxtotal
FROM (SELECT ClassId, MAX(
coalesce(exam1,0)+
coalesce(exam2,0)
) as 'maxtotal'
FROM workbook
WHERE
(
termid = '11'
)
GROUP BY ClassId) s1
JOIN workbook s2 ON s1.ClassId = s2.ClassId
WHERE s1.maxtotal = (
coalesce(exam1,0)+
coalesce(exam2,0)
) AND (s1.maxtotal >'75');
last line is good for s1.maxtotal=0 (some times student scores have not be entered and all equals 0 so all will shown as best students) or some times we need minimum score (to enroll in next term).
So thanks all
I'am a beginner in SQL and have some trouble with joining and counting at the same time.
First let me explain my two tables.
I have the following:
Table: AnalysePageview
id title session more
-----------------------------------------------------
1 a 10 0
2 b 20 1
3 c 30 1
4 d 40 1
5 e 50 1
6 f 60 0
Table: AnalyseEvent
id name session more
-----------------------------------------------------
1 a 10 0
2 b 10 1
3 c 10 1
4 d 20 1
and I would like to join this two and add a line like this:
New Table:
id name session counts (out off AnalyseEvent)
-----------------------------------------------------
1 a 10 3
2 b 20 1
3 c 30 0
4 d 40 0
5 e 50 0
6 f 60 0
I just tried this:
SELECT *,
COUNT( AnalyseEvent.session ) AS totalViews
FROM AnalysePageview
LEFT JOIN AnalyseEvent ON AnalysePageview.session = AnalyseEvent.session
thanks for any help in advance. (my be with a small beginner explanation)
You need a group by:
SELECT apv.id, apv.name, apv.session, COUNT( ae.session ) AS totalViews
FROM AnalysePageview apv LEFT JOIN
AnalyseEvent ae
ON apv.session = ae.session
GROUP BY apv.id, apv.name, apv.session;
I also added table aliases to make the query easier to write and to read.
You need to use group by. Something like:
select apw.id, apw.title, apw.session, count(1)
from AnalysePageview apw
left join AnalyseEvent ae
on apw.session = ae.session
group by apw.id, apw.title, apw.session
I have a table with columns similar to below , but with about 30 date columns and 500+ records
id | forcast_date | actual_date
1 10/01/2013 12/01/2013
2 03/01/2013 06/01/2013
3 05/01/2013 05/01/2013
4 10/01/2013 09/01/2013
and what I need to do is get a query with output similar to
week_no | count_forcast | count_actual
1 4 6
2 5 7
3 2 1
etc
My query is
SELECT weekofyear(forcast_date) as week_num,
COUNT(forcast_date) AS count_forcast ,
COUNT(actual_date) AS count_actual
FROM
table
GROUP BY
week_num
but what I am getting is the forcast_date counts repeated in each column, i.e.
week_no | count_forcast | count_actual
1 4 4
2 5 5
3 2 2
Can any one please tell me the best way to formulate the query to get what I need??
Thanks
try:
SELECT weekofyear(forcast_date) AS week_forcast,
COUNT(forcast_date) AS count_forcast, t2.count_actual
FROM
t t1 LEFT JOIN (
SELECT weekofyear(actual_date) AS week_actual,
COUNT(forcast_date) AS count_actual
FROM t
GROUP BY weekOfYear(actual_date)
) AS t2 ON weekofyear(forcast_date)=week_actual
GROUP BY
weekofyear(forcast_date), t2.count_actual
sqlFiddle
You have to write about 30 (your date columns) left join, and the requirement is that your first date column shouldn'd have empty week (with a count of 0) or the joins will miss.
Try:
SELECT WeekInYear, ForecastCount, ActualCount
FROM ( SELECT A.WeekInYear, A.ForecastCount, B.ActualCount FROM (
SELECT weekofyear(forecast_date) as WeekInYear,
COUNT(forecast_date) as ForecastCount, 0 as ActualCount
FROM TableWeeks
GROUP BY weekofyear(forecast_date)
) A
INNER JOIN
( SELECT * FROM
(
SELECT weekofyear(forecast_date) as WeekInYear,
0 as ForecastCount, COUNT(actual_date) as ActualCount
FROM TableWeeks
GROUP BY weekofyear(actual_date)
) ActualTable ) B
ON A.WeekInYear = B.WeekInYear)
AllTable
GROUP BY WeekInYear;
Here's my Fiddle Demo
Just in case someone else comes along with the same question:
Instead of trying to use some amazing query, I ended up creating an array of date_columns_names and a loop in the program that was calling this query, and for each date_column_name, performing teh asme query. It is a bit slower, but it does work