Basicly I have tables much like picture below.
At first I'm getting SaleOrderID by given CustomerID :
Select
SaleOrderID
From tblSaleOrder
where CustomerID = 512992
Which returns, 1002,1003,1005,1009
And I want to use that numbers for select from tblSaleOrderDetail :
Select
*
from tblSaleOrderDetail
where SaleOrderID = 1002,1003,1005,1009
(values from other query)
I need suggestion on query to use values from another select. Is there a way to create array to hold values then use it for another query ? OR a easier way !
Use a subselect within an in clause:
select *
from tblSaleOrderDetail
where SaleOrderID in (
select SaleOrderID
from tblSaleOrder
where CustomerID = 512992)
When using a subselect within an in clause remember that you must only select one column within the subselect.
You could also perform a join:
select *
from tblSaleOrderDetail sod
join tblSaleOrder so
on sod.SaleOrderId = so.SaleOrderId
where so.CustomerID = 512992
This is a very basic SQL operation, called the join. Although you can use in for this purpose, the more typical way is:
select sod.*
from tblSaleOrder so join
tblSaleOrderDetail sod
on so.SaleOrderID = sod.SaleOrderID
where so.CustomerID = 512992;
If you are learning SQL, the join operation is one of the first things you should be learning.
Probably going a bit overkill on this post since the question is fairly basic but I wanted to give you a list of options as well as some basic advice. One of the simplest ways to do this is by using the IN clause. The IN clause conceptually works a lot like = except it looks for a list of items.
Example
Select
*
from tblSaleOrderDetail
where SaleOrderID IN
(
Select
SaleOrderID
From tblSaleOrder
where CustomerID = 512992
)
Yet another way to accomplish this is by using EXISTS. Which works very much like it sounds it checks for rows that exist in the other table.
Select
*
from tblSaleOrderDetail AS SOD
where EXISTS
(
Select
1
From tblSaleOrder AS SO
where CustomerID = 512992
AND SOD.SaleOrderID = SO.SaleOrderID
)
Notice how I use AS SO and SOD to give those tables new names. This is called aliasing and it is your friend. I highly recommend using it in you future queries.
You can use JOIN as well however when I started writing this there was already an example of this.
Related
I want to get * from concrete_samples but only method_name and not the id from concrete_compaction_methods
SELECT * FROM concrete_samples,concrete_compaction_methods WHERE concrete_compaction_methods.id = concrete_samples.compaction_method AND workorder_id=1
This is currently returning everything I want EXCEPT it's giving me the id column of the methods table which I don't want.
the pseudo code of the statement I want to do is
SELECT * FROM concrete_samples, SELECT method_name FROM concrete_compaction_methods WHERE concrete_compaction_methods.id = concrete_samples.compaction_method AND workorder_id=1
I've done some research. I've tried to use a union but i don't think that's the correct or neatest solution
Thank you
I strongly advise:
Learn to use proper JOIN syntax.
Use table aliases in your query.
Qualify all column references.
So the query looks more like this:
SELECT cs.*, ccm.method_name
FROM concrete_samples cs JOIN
concrete_compaction_methods ccm
ON ccm.id = cs.compaction_method
WHERE cs.workorder_id = 1;
I am guessing that workorder_id comes from concrete_samples rather than the other table.
Try below -
SELECT concrete_samples.*,method_name
FROM concrete_samples inner join concrete_compaction_methods
on concrete_compaction_methods.id = concrete_samples.compaction_method
where workorder_id=1
I have the following query:
select x.id0
from (
select *
from sessions
inner join clicked_products on sessions.id0 = clicked_products.session_id0
) x;
Since id0 is in both sessions and clicked_products, I get the expected error:
column reference "id0" is ambiguous
However, to fix this problem in the past I simply needed to specify a table. In this situation, I tried:
select sessions.id0
from (
select *
from sessions
inner join clicked_products on sessions.id0 = clicked_products.session_id0
) x;
However, this results in the following error:
missing FROM-clause entry for table "sessions"
How do I return just the id0 column from the above query?
Note: I realize I can trivially solve the problem by getting rid of the subquery all together:
select sessions.id0
from sessions
inner join clicked_products on sessions.id0 = clicked_products.session_id0;
However, I need to do further aggregations and so do need to keep the subquery syntax.
The only way you can do that is by using aliases for the columns returned from the subquery so that the names are no longer ambiguous.
Qualifying the column with the table name does not work, because sessions is not visible at that point (only x is).
True, this way you cannot use SELECT *, but you shouldn't do that anyway. For a reason why, your query is a wonderful example:
Imagine that you have a query like yours that works, and then somebody adds a new column with the same name as a column in the other table. Then your query suddenly and mysteriously breaks.
Avoid SELECT *. It is ok for ad-hoc queries, but not in code.
select x.id from
(select sessions.id0 as id, clicked_products.* from sessions
inner join
clicked_products on
sessions.id0 = clicked_products.session_id0 ) x;
However, you have to specify other columns from the table sessions since you cannot use SELECT *
I assume:
select x.id from (select sessions.id0 id
from sessions
inner join clicked_products
on sessions.id0 = clicked_products.session_id0 ) x;
should work.
Other option is to use Common Table Expression which are more readable and easier to test.
But still need alias or selecting unique column names.
In general selecting everything with * is not a good idea -- reading all columns is waste of IO.
I just hit a wall with my SQL query fetching data from my MS SQL Server.
To simplify, say i have one table for sales, and one table for customers. They each have a corresponding userId which i can use to join the tables.
I wish to first SELECT from the sales table where say price is equal to 10, and then join it on the userId, in order to get access to the name and address etc. from the customer table.
In which order should i structure the query? Do i need some sort of subquery or what do i do?
I have tried something like this
SELECT *
FROM Sales
WHERE price = 10
INNER JOIN Customers
ON Sales.userId = Customers.userId;
Needless to say this is very simplified and not my database schema, yet it explains my problem simply.
Any suggestions ? I am at a loss here.
A SELECT has a certain order of its components
In the simple form this is:
What do I select: column list
From where: table name and joined tables
Are there filters: WHERE
How to sort: ORDER BY
So: most likely it was enough to change your statement to
SELECT *
FROM Sales
INNER JOIN Customers ON Sales.userId = Customers.userId
WHERE price = 10;
The WHERE clause must follow the joins:
SELECT * FROM Sales
INNER JOIN Customers
ON Sales.userId = Customers.userId
WHERE price = 10
This is simply the way SQL syntax works. You seem to be trying to put the clauses in the order that you think they should be applied, but SQL is a declarative languages, not a procedural one - you are defining what you want to occur, not how it will be done.
You could also write the same thing like this:
SELECT * FROM (
SELECT * FROM Sales WHERE price = 10
) AS filteredSales
INNER JOIN Customers
ON filteredSales.userId = Customers.userId
This may seem like it indicates a different order for the operations to occur, but it is logically identical to the first query, and in either case, the database engine may determine to do the join and filtering operations in either order, as long as the result is identical.
Sounds fine to me, did you run the query and check?
SELECT s.*, c.*
FROM Sales s
INNER JOIN Customers c
ON s.userId = c.userId;
WHERE s.price = 10
I couldn't be more specific in the title part but I want to do something a little bit complex for me. I thought I did it but it turned out that it is buggy.
I have three tables as following:
ProjectTable
idProject
title
idOwner
OfferTable
idOffer
idProject
idAccount
AccountTable
idAccount
Username
Now in one query I aim to list all the projects with most offers made, and in the query I also want to get details like the username of the owner, username of the offerer* etc. So I don't have to query again for each project.
Here is my broken query, it's my first experiment with GROUP BY and I probably didn't quite get it.
SELECT Project.addDate,Project.idOwner ,Account.Username,Project.idProject,
Project.Price,COUNT(Project.idProject) as offercount
FROM Project
INNER JOIN Offer
ON Project.idProject= Offer.idProject
INNER JOIN Account
ON Account.idAccount = Project.idOwner
GROUP BY Project.addDate,Project.idOwner,
Account.Username,Project.idProject,Project.Price
ORDER BY addDate DESC
*:I wrote that without thinking I was just trying to come up with example extra information, that is meaningless thanks to Hosam Aly.
Try this (modified for projects with no offers):
SELECT
Project.addDate,
Project.idOwner,
Account.Username,
Project.idProject,
Project.Price,
ISNULL(q.offercount, 0) AS offercount
FROM
(
SELECT
o.idProject,
COUNT(o.idProject) as offercount
FROM Offer o
GROUP BY o.idProject
) AS q
RIGHT JOIN Project ON Project.idProject = q.idProject
INNER JOIN Account ON Account.idAccount = Project.idOwner
ORDER BY addDate DESC
I might switch the query slightly to this:
select p.addDate,
p.idOwner,
a.Username,
p.idProject,
p.price,
o.OfferCount
from project p
left join
(
select count(*) OfferCount, idproject
from offer
group by idproject
) o
on p.idproject = o.idproject
left join account a
on p.idowner = a.idaccount
This way, you are getting the count by the projectid and not based on all of the other fields you are grouping by. I am also using a LEFT JOIN in the event the projectid or other id doesn't exist in the other tables, you will still return data.
Your question is a bit vague, but here are some pointers:
To list the projects "with most offers made", ORDER BY offercount.
You're essentially querying for projects, so you should GROUP BY Project.idProject first before the other fields.
You're querying for the number of offers made on each project, yet you ask about offer details. It doesn't really make sense (syntax-wise) to ask for the two pieces of information together. If you want to get the total number of offers, repeated in every record of the result, along with offer information, you'll have to use an inner query for that.
An inner query can be made either in the FROM clause, as suggested by other answers, or directly in the SELECT clause, like so:
SELECT Project.idProject,
(SELECT COUNT(Offer.idOffer)
FROM Offer
WHERE Offer.idProject = Project.idProject
) AS OfferCount
FROM Project
I was trying to achieve this query1:
UPDATE temp_svn1 t set closedate=(select max(date) from temp_svn1 p where p.id=t.id
Apparently MySQL does not allow such queries. So I came up with this query using inner joins but this is too slow. How can I write a better query for this? OR How can I achieve the logic of query 1?
UPDATE temp_svn1 AS out INNER JOIN (select id, close from temp_svn1 T inner join (select id as cat, max(date) as close from temp_svn1 group by cat) as in where T.id = in.cat group by id ) as result ON out.id = result.id SET out.closedate = result.close
Because of mysql peculiarities the only way you're going to get this to be faster is to split it into two statements. First, fetch the max, and then use it in an update. This is a known hack, and, afaik, there's not a "neater" way of doing it in a single statement.
Since your subquery is just returning a single value, you could do the query in two stages. Select the max(date) into a server-side variable, then re-use that variable in the outer query. Of course, this breaks things up into two queries and it'll no longer be atomic. But with appropriate transactions/locks, that becomes moot.
This works:
UPDATE temp_svn1
set closedate = (select max(date) from temp_svn1 p where p.id = temp_svn1.id)