Using join in place of this sub-query in MySQL - mysql

I have a table by the following structure and records, All i want to do is to just extract orderid of those records whose status id is either 1 or 2 , i want to exclude all orderid with statusid=3 , , problem is that orderid 106 has both status 1 and 3 ...
I have written a sub-query which serves the purpose..
select *
from orders_status_history
where orders_id NOT IN
(select orders_id
from orders_status_history
where orders_status_id = 3)
is there any other way of doing this without using sub-queries as i have heard it hampers performance. As my query can return thousands of rows as well.
id order-id status-id
1 1 1
2 2 1
3 105 1
4 106 1
5 106 3
6 108 1
7 109 1
8 109 2
Any help or suggestion will be highly appreciated ..Thanks in advance..

You may do that:
SELECT osh.*
FROM orders_status_history osh
LEFT JOIN
orders_status_history oshd
ON oshd.orders_id = osh_orders_id
AND oshd.orders_status_id = 3
WHERE oshd.orders_id IS NULL
However, if you have an index on order_status_history (orders_id, orders_status_id), then the NOT IN query is just as fine.
You may want to read this:
NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL: MySQL

I wonder why you use sub query while you can use the following query
select orders_id from orders_status_history where orders_status_id <> 3
Please try this , and I hope it helps

Related

Count ID in sql query

I have the following data,
id emp_id csa_taken
1 100 2
2 100 2
3 100 0
4 100 2
5 101 2
6 101 2
7 101 0
8 101 0
I expect a result with count where csa_taken=2 for individual employee.
expected result:
emp_id count_csa_taken
100 3
101 2
I have tried the following query with a failed attempt.
Select count(employee_id) From $employeeCSA where csa_taken=2
Please suggest as I am new to sql.
If I understand you correctly you like to count all employees with a cas_taken of two. As there are multiple entries for the csa_taken for one employee you need to group them.
E.g.:
SELECT COUNT(*) FROM $employeeCSA WHERE csa_taken = 2 GROUP_BY employee_id
Please note that COUNT(*) counts the rows (not the fields).
You also need group by. Try like:
Select count(employee_id),emp_id From $employeeCSA where csa_taken=2
group by emp_id
If i understand correctly, then you can try this:
SELECT emp_id,COUNT(emp_id) from dbo.Sample WHERE csa_token = 2 GROUP BY emp_id

Sql select where a column has been set atleast once

I have this table
**applications**
id user_id company_id shortlisted
1 10 99 0
2 10 100 1
3 10 101 1
4 10 102 0
5 11 99 1
6 12 99 0
6 12 101 0
What I want is to select all users
which have been shortlisted at-least once
which have not been shortlisted at all
For the first case, i have the following query:
SELECT user_id
from applications
where shortlisted=1
Group
By user_id
and this gives me the expected result like below
**applications**
user_id
10
11
But I'm trying the following query for the second case and it returns me an empty set:
Select user_id
from applications as Application
where shortlisted=0
and NOT EXISTS(Select user_id from applications where user_id=Application.user_id and shortlisted=1)
What am i missing?
PS: Please ignore any typos as i typed them manually for this post.
To get both results in a single query simply use aggregation:
select user_id, max(shortlisted) as was_shortlisted
from applications
group By user_id
You can use group by and having for both.
For the first:
select user_id
from applications
group By user_id
having max(shortlisted) = 1;
For the second:
select user_id
from applications
group By user_id
having max(shortlisted) = 0;
In all honesty, your version with the where is more efficient for the first query. This is just to show how closely related the queries are.
You can try following query;
select user_id from table1
group by user_id having MIN(shortlisted) = 1
This will give you to at least have shortlisted = 1 condition and don't have shortlisted = 0 records.

MySQL Get rows that do not match with certain conditions

It seems simple in my head but I am at a loss for getting the results I need.
My table
id, code, type
1 1111 1
2 1111 2
3 1222 1 <--- This one
4 1333 1
5 1333 2
6 1444 3 <--- Different type then the others
I want the output of the one that doesn't have a matching code with type 2 but only look for ones with type 1 or type 2 (if that makes sense)
id, code, type
3 1222 1
NOTE: I have over 1 million records to query so I need something fast.
My SqlFiddle
Thanks in advance.
SELECT * FROM codes NATURAL JOIN (
SELECT code
FROM codes
WHERE type IN (1,2)
GROUP BY code
HAVING COUNT(DISTINCT type) = 1
) t
See it on sqlfiddle.
Here is a solution using not exists:
SELECT c.*
FROM codes c
WHERE c.type = 1 and
not exists (select 1
from codes c2
where c2.code = c.code and
c2.type = 2
)

MySQL Group by week num w/ multiple date column

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

Mysql Count per column

I have the following query:
SELECT a.feeder_id, b.feeder_pr
FROM authors_article_feeders a
LEFT JOIN feeders b ON b.id = a.feeder_id
WHERE website_id =1
LIMIT 0 , 30
which results in:
feeder_id feeder_pr
18 2
18 2
18 2
18 2
32 6
What I need is to modify the above query so that it will manipulate this data so that the result would end up with a count of each feeder_pr, so in this case the result would be:
feeder_pr count
2 4
6 1
Any assistance is appreciated. If you have time please describe your solution so that I can learn from it while I'm at it.
Everything I've tried has ended in inaccurate results, usually with just one row instead of the expected 2.
You just need to add a GROUP BY And, you would not even need the joins
SELECT b.feeder_pr, COUNT(b.feeder_pr)
FROM feeders b
GROUP BY b.feeder_pr
SELECT b.feeder_pr, count(a.feeder_id) as count
FROM authors_article_feeders a
LEFT JOIN feeders b ON b.id = a.feeder_id
WHERE website_id =1
GROUP BY 1