Get subquery value in main query - sql

I am using the below query to get the customer detail. But it's not working please help me. I am new for SQL.
select cu.fld_cust_id,ord.* from test1 where fld_order_id ord in (select * from tbl_customer cu where cu.fld_status=1);

You can't select columns from subquery used in WHERE clause, becaused they are not joined to this query. You are just using value range returned from this subquery
Your subquery should return only one column here.
You should try something like this.
SELECT cu.fld_cust_id,ord.*
FROM test1
JOIN tbl_customer cu ON cu.fld_status=1 AND fld_order_id = cu.fld_cust_id

Not sure what's in your tbl_customer, but seems like you are matching the fld_order_id to *. You should match with the order_id in your customer table.
select cu.fld_cust_id,ord.*
from test1
where fld_order_id ord in (
select *ORDERID* from tbl_customer cu where cu.fld_status=1
);

In a query you also need to be aware that you can only see the fields in the current scope. So in the main query you only use FROM TEST1, therefore you can only see the fields from that table. ord.* and the use of cu will give an error. If you need other fields from that table use a JOIN. The TEST1 table should contain a foreign key that links to TBL_CUSTOMER, if not you need either a path using other other tables or redesign your database. If you have that foreign key, that's what you use around the IN operator:
select fld_cust_id from test1 where fld_cust_id in (select id from tbl_customer cu where cu.fld_status=1);

Related

Using Select * in a SQL JOIN returns the wrong id value for the wrong table

I have two tables (PlayerDTO and ClubDTO) and am using a JOIN to fetch data as follows:
SELECT * FROM PlayerDTO AS pl
INNER JOIN ClubDTO AS cl
ON pl.currentClub = cl.id
WHERE cl.nation = 7
This returns the correct rows from PlayerDTO, but in every row the id column has been changed to the value of the currentClub column (eg instead of pl.id 3,456 | pl.currentClub 97, it has become pl.id 97 | pl.currentClub 97).
So I tried the query listing all the columns by name instead of Select *:
SELECT pl.id, pl.nationality, pl.currentClub, pl.status, pl.lastName FROM PlayerDTO AS pl
INNER JOIN ClubDTO AS cl
ON pl.currentClub = cl.id
WHERE cl.nation = 7
This works correctly and doesn’t change any values.
PlayerDTO has over 100 columns (I didn’t list them all above for brevity, but I included them all in the query) but obviously I don’t want to write every column name in every query.
So could somebody please explain why Select * changes the id value and what I need to do to make it work correctly? All my tables have a column called id, is that something to do with it?
SELECT *... is, according to the docs...
shorthand for “select all columns.” (Source: Dev.MySQL.com
Both your tables have id columns, so which should be returned? It's not indicated, so MySQL makes a guess. So select what you want to select...
SELECT pl.id, *otherfieldsyouwant* FROM PlayerDTO AS pl...
Or...
SELECT pl.* FROM PlayerDTO AS pl...
Typically, SELECT * is bad form. The odds you are using every field is astronomically low. And the more data you pull, the slower it is.

Why do I get a duplicate column name error only when I SELECT FROM (SELECT)

I imagine this is a really basic oversight on my part but I have an SQL query which works fine. But I when I SELECT from that result (SELECT FROM (SELECT))
I get a 'duplicate column' error. There are duplicate column names, for sure, in two tables where I compare them but they do not cause a problem in the initial result. For example:
SELECT _dia_tagsrel.tag_id,_dia_tagsrel.article_id, _dia_tags.tag_id, _dia_tags.tag
FROM _dia_tagsrel
JOIN _dia_tags
ON _dia_tagsrel.tag_id = _dia_tags.tag_id
Works fine but when I try to select from it, I get the error:
SELECT DISTINCT tag FROM
(SELECT _dia_tagsrel.tag_id,_dia_tagsrel.article_id, _dia_tags.tag_id, _dia_tags.tag
FROM _dia_tagsrel
JOIN _dia_tags
ON _dia_tagsrel.tag_id = _dia_tags.tag_id) a
Regardless of the DISTINCT. Ok, I can change the column names to be unique but the question really is - why do i get the error when I SELECT FROM (SELECT) and not in the initial query?
Thanks
Solution:
SELECT DISTINCT tag_id, tag FROM (SELECT _dia_tagsrel.tag_id, _dia_tagsrel.article_id, _dia_tags.tag
FROM _dia_tagsrel
JOIN _dia_tags
ON _dia_tagsrel.tag_id = _dia_tags.tag_id) a
I only needed to SELECT one of the duplicate columns, even though I was comparing the both of them. Provided by answer below.
In you are second query i.e., the sub query, you are selecting tag_id twice. Though it is from two different tables, it works out whey you are selecting the data. But when you select the columns with same name twice, it provides you duplicate error. Below is the way you have selected the column which is incorrect
_dia_tagsrel.tag_id,_dia_tagsrel.article_id, _dia_tags.tag_id, _dia_tags.tag
While using sub queries, merge, in or exists clause, avoid using the same column names multiple times.
Simple join works out no need of having subquery,
SELECT _dia_tagsrel.tag_id,_dia_tagsrel.article_id, _dia_tags.tag_id, _dia_tags.tag
FROM _dia_tagsrel
JOIN _dia_tags
ON _dia_tagsrel.tag_id = _dia_tags.tag_id
Your first query returns four columns:
tag_id
article_id
tag_id
tag
Duplicate column names are allowed in a result set, but are not allowed in a table -- or derived table, view, CTE, or most subqueries (an exception are EXISTS subqueries).
I hope you can see the duplicate. There is no need to select tag_id twice, because the JOIN requires that the values are the same. So just select three columns:
SELECT tr.tag_id, tr.article_id, t.tag
FROM _dia_tagsrel tr JOIN
_dia_tags t
ON tr.tag_id = t.tag_id
Your subquery has two tag_ids, so how database engine decide which one you want to use.
So, either use one (join requires tag_ids to be same) or re-name it :
If _dia_tag has unique tags then you can use EXISTS instead of INNER JOIN:
SELECT t.tag
FROM _dia_tags t
WHERE EXISTS (SELECT 1 FROM _dia_tagsrel tr WHERE tr.tag_id = t.tag_id);

How to use a SQL table instead of a long string for a WHERE in (string) condition

I have the following SQL statement:
select customer_id, prod_id, prod_start, prod_price
from prod_table
where prod_id in (PRODLIST)
Unfortunately, PRODLIST contains about 68K 6-digit numbers. When I try to run this query on my server, I get an error that SQL can't handle so many prod_id as presented in a string.
My next thought was to put all the 68K 6-digit numbers into a single column table included_prodlist with column heading included_prod_id. The resulting included_prodlist table would then be a single column table with 68K rows, and each column would be a unique 6-digit number.
I could then do an inner join of the original query with included_prodlist as follows:
select customer_id, prod_id, prod_start, prod_price
from prod_table
where prod_id in (select included_prod_id from included_prodlist)
Unfortunately, this doesn't seem to be working i.e. the query returns no entries.
Is this the proper way to deal with long conditions?
Should I be using an inner join instead?
select customer_id, prod_id, prod_start, prod_price
from prod_table
inner join included_prodlist on prod_table.prod_id = included_prodlist.included_prod_id
Putting the values in to a table is highly recommended. The one column should be the primary key.
Then, I would go for exists rather than not in:
select p.customer_id, p.prod_id, p.prod_start, p.prod_price
from prod_table p
where exists (select 1
from included_prodlist ip
where ip.included_prod_id = p.prod_id
);
Of course using INNER JOIN can be more helpful with a better performance. For best practices create the index which is recommended in query execution plan :)
INNER JOIN on a single column table is preferable on a nested query
In a nested query the internal query runs 1st and its results are placed in the outer query
Using join, there is only one query, preferably on indexed columns
You will be able to see the differences adding EXPLAIN before the SELECT command
I would generate the product list table as a temp table, with an indexed column, that way the query would run with join even faster

Search table based on infromation from another table

I have created a temporary that has been populated correctly but now I want to search another table based on two fields that are contained within my temporary table. These fields are Forename and Surname. But I want to search for multiple student names and quantities and return specified data! I think the problem will be better explained in the images below:
My Temporary Table
The Table I would like to search (Table2)
Once I have searched each student name I want to be returned with the students Forename, Surname Address, Pin and Score!
Below shows how I have been trying to achieve this without any luck!
Select TempTable.Forname, TempTable.Surmname, Table2.Address, Table2.Pin
from TempTable
Where Exists ( Select * from Table2
where Table2.Forname=TempTable.Forname and
Table2.Surname=TempTable.Surname
)
But it is returning me no results and I don't know why!
If i understand correctly your question, the way to do it is just a simple join:
select TempTable.Forename, TempTable.Surname, Table2.Address, Table2.Pin
from TempTable
inner join Table2 on Table2.Forename = TempTable.Forename and Table2.Surname = TempTable.Surname
Though i recommend you to have a primary key on the "Persons" table (Table2) and use this primary key to reference the records on TepTable
The EXISTS is only used to "filter" result, it's columns aren't available outside the EXISTS.
You need a JOIN!
Select TempTable.Forname, TempTable.Surmname, Table2.Address, Table2.Pin
from TempTable JOIN Table2 ON Table2.Forname=TempTable.Forname and Table2.Surname=TempTable.Surname;
Assuming you really have called the columns "Forname" you just need a simple join. This does it explicitly to keep close to your original:
SELECT TempTable.Forname, TempTable.Surmname, Table2.Address, Table2.Pin
FROM TempTable tt, Table2 t2
WHERE tt.Forename = t2.Forename
AND tt.Surname = t2.Surname;
You could do the same with INNER JOIN.
This is all assuming that student names are unique.

Replacing Not In clause in sql query

I have a temporary table #allocations
which has the following fields
DAllocationId DAllocationName FundCode DSplitTotal DDisabled DistAlloc AAllocationId AAllocationName ASplitTotal ADisabled
I have another table TRAN_POST_PTN which also has these columns along with other columns.
So for asplit id and dsplit id we just have the same column name which is "posting number" in TRAN_POST_PTN.
What i need to do is insert into my allocations table all the rows from TRAN_POST_PTN where the
posting_number is not in (select DAllocationId from #allocations)
and posting_number not in (select AAllocationId from #allocations)
I do not want to use Not in here.
Can some one please suggest me a better way of writing this query.
I tried writing it using union,but that did not work.
There are a couple alternatives to NOT IN. Here's one using NOT EXISTS:
SELECT fields
FROM TRAN_POST_PTN tpp
WHERE NOT EXISTS (
SELECT 1
FROM #allocations a
WHERE tpp.posting_number IN (a.DAllocationId, a.AAllocationId))
Another common way is to use LEFT JOIN with NULL checks, but I believe you'll see a better performance with NOT EXISTS.
SELECT fields
FROM TRAN_POST_PTN tpp
LEFT JOIN #allocations a ON tpp.posting_number = a.DAllocationId
OR tpp.posting_number = a.AAllocationId
WHERE a.DAllocationId IS NULL