Use a select query result in an other query - sql

Could please someone explain, how to use a result from a SELECT (1st select result)
Then use that result (1st select result) on a second query VALUES clause
there is an example (on Microsoft SQL Server) :
--1st query, select all DB1.client.name
select Name from DB1.client
--the result of that query is : 1st select result VALUES : ana,boby, ..., micky
--2nd query, compare DB1.client.name (1st select result) with DB2.client.name
--and get back who doesn't exist on second table
select v.Name
from (values
**(There i want use the result of my first query)**
) as v(Name)
where not exists (select *
from DB2.client c
where c.Name = v.Name);
--the result is ana, ..., micky
"..." mean some other results
i want compare first and second database to retrieve values which aren't in both databases

If you can, I recommend sub-query :
select Name
from DB1.client
where Name not in not exists (select name from DB2.client)
If you want reuse a query (not the result), see #Thkas answer.
It isn't possible to reuse the result in SQL Server, because SQL Server release the memory when the result is read. The trick is to insert the query's result in a temporary table, then you read this temporary table as many times as necessary :
--Insert into temporary table
insert into #tmpResult
select Name from DB1.client
--First read
select Name from #tmpResult
--Second read from sub-query
select Name
from #tmpResult
where Name not in not exists (select name from DB2.client)

According to your sample code I understood something like this. You can add two tables and do with WHERE the check you want.
select a.Name,b.Name
from DB1.client,
DB2.client as b
where a.Name != b.Name;
Also if you want to take as a result set from the first query:
Here I created a subquery which takes the results from the first query. You can correct me for columns.
with temp as (
select Name
from DB1.client
)select a.Name,b.Name
from temp as a ,
DB2.client as b
where a.Name != b.Name;

Related

SELECT VALUES in Teradata

I know that it's possible in other SQL flavors (T-SQL) to "select" provided data without a table. Like:
SELECT *
FROM (VALUES (1,2), (3,4)) tbl
How can I do this using Teradata?
Teradata has strange syntax for this:
select t.*
from (select * from (select 1 as a, 2 as b) x
union all
select * from (select 3 as a, 4 as b) x
) t;
I don't have access to a TD system to test, but you might be able to remove one of the nested SELECTs from the answer above:
select x.*
from (
select 1 as a, 2 as b
union all
select 3 as a, 4 as b
) x
If you need to generate some random rows, you can always do a SELECT from a system table, like sys_calendar.calendar:
SELECT 1, 2
FROM sys_calendar.calendar
SAMPLE 10;
Updated example:
SELECT TOP 1000 -- Limit to 1000 rows (you can use SAMPLE too)
ROW_NUMBER() OVER() MyNum, -- Sequential numbering
MyNum MOD 7, -- Modulo operator
RANDOM(1,1000), -- Random number between 1,1000
HASHROW(MyNum) -- Rowhash value of given column(s)
FROM sys_calendar.calendar; -- Use as table to source rows
A couple notes:
make sure you pick a system table that will always be present and have rows
if you need more rows than are available in the source table, do a UNION to get more rows
you can always easily create a one-column table and populate it to whatever number of rows you want by INSERT/SELECT into it:
CREATE DummyTable (c1 INT); -- Create table
INSERT INTO DummyTable(1); -- Seed table
INSERT INTO DummyTable SELECT * FROM DummyTable; -- Run this to duplicate rows as many times are you want
Then use this table to create whatever resultset you want, similar to the query above with sys_calendar.calendar.
I don't have a TD system to test so you might get syntax errors...but that should give you a basic idea.
I am a bit late to this thread, but recently got the same error.
I solved this by simply using
select distinct 1 as a, 2 as b from DBC.tables
union all
select distinct 3 as a, 4 as b from DBC.tables
Here, DBC.tables is a DB backend table with a few rows only. So, the query runs fast as well

(Teradata Version)- get all records plus all corresponding records in another table

Can following Query be optimised for Teradata?
We need all records from small table A, plus all corresponding records from large table B, that match on a nonunique key
Or, in other words: everything except all from B that has no match in A.
Maybe something with a JOIN? Or a Subselect that is a non-correlated Query, does that also apply to Teradata?
SELECT a.nonunique
, a.colX
FROM small_tab a
UNION ALL
SELECT b.nonunique
, b.colY
FROM large_tab b
WHERE EXISTS (
SELECT 1
FROM small_tab a
WHERE a.nonuniqe = b.nonunique
);
Thanks for the help!
=========UPDATE====
based on quanos answer in this MySQL question, would following statement with a noncorrelated subquery be faster also in Teradata?
SELECT a.nonunique
, a.colX
FROM small_tab a
UNION ALL
SELECT b.nonunique
, b.colY
FROM large_tab b
WHERE b.nonunique IN
(
SELECT DISTINCT nonunique
FROM small_tab
GROUP BY nonunique
)
I cannot test in Teradata currently, only have an Oracle instance at home..
I'm not sure whether it is a typo, but you have a redundant select query after WHERE clause. Also, you will have to use the same column name in SELECT query that is being used in WHERE Claue.
Below query works fine in Teradata.
SELECT a.nonunique, a.colX
FROM small_tab a
UNION ALL
SELECT b.nonunique, b.colY
FROM large_tab b
WHERE b.id IN(
SELECT **id**
FROM small_tab)
Hope it helps. if any query on above query, please let me know.

SQL Server error - Subquery returned more than 1 value

I'm looking to insert rows of data into a table from another table, normal scenario.
Here's my current SQL script,
INSERT [dbo].[X_RPT_PORTAL_REPORTLIST] (
[PORTAL_GROUP_ID],
[REPORT_DISPLAY_NAME],
[STANDARD_REPORT],
[REPORT_PACK_VERSION],
[REPORT_PATH]
)
VALUES (
(SELECT ID FROM X_RPT_REPORTINGLIST),
(SELECT REPORT_NAME FROM X_RPT_REPORTINGLIST),
(SELECT STANDARD_REPORT FROM X_RPT_REPORTINGLIST),
(SELECT REPOPT_PACK_VERSION FROM X_RPT_REPORTINGLIST),
(SELECT PATH FROM ReportServer$PORTAL.dbo.Catalog)
)
Now my error I had return from this was:
Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I had a thought this maybe incorrect, but I need some pointers on getting around this.
Any help or tips, is much appreciated.
Thank you
This issue arose because one or more of the subqueries you have used to provide the data for VALUES() have returned multiple records. The VALUES() construct is used by INSERT to insert one and only one record.
This usually arises when people use WHERE conditions such as WHERE value = (SELECT value FROM sub_table) and the subquery returns multiple records; hence is why the error message was versed as it was.
It is possible to follow an INSERT statement with a SELECT statement which returns the data that you want put into the table, so consider the following:
INSERT [dbo].[X_RPT_PORTAL_REPORTLIST] (
[PORTAL_GROUP_ID],
[REPORT_DISPLAY_NAME],
[STANDARD_REPORT],
[REPORT_PACK_VERSION],
[REPORT_PATH])
SELECT
r.ID
,r.REPORT_NAME
,r.STANDARD_REPORT
,r.REPOPT_PACK_VERSION
,c.PATH
FROM X_RPT_REPORTINGLIST r
CROSS JOIN ReportServer$PORTAL.dbo.Catalog c;
You're attempting to insert one row into a table and can therefore only have one value for each column in the row. This error means is that one or more of the SELECT statements in your VALUES() clause is returning more than one value.
Run each of the SELECT statements individually and see which of them are returning multiple rows and then constrain them with a WHERE clause where necessary until you get the single value from each of them that you want.
I think the error message is clear. You want to switch to insert . . . select. Something like this:
INSERT [dbo].[X_RPT_PORTAL_REPORTLIST] ([PORTAL_GROUP_ID], [REPORT_DISPLAY_NAME], [STANDARD_REPORT], [REPORT_PACK_VERSION], [REPORT_PATH])
SELECT rl.ID, rl.REPORT_NAME, rl.STANDARD_REPORT, rl.REPORT_PACK_VERSION,
c.PATH
FROM X_RPT_REPORTINGLIST JOIN
ReportServer$PORTAL.dbo.Catalog c
ON rl.??? = c.???;
It is unclear what the JOIN conditions are. If there is only one path, then you might want a CROSS JOIN.
Run following queries separately. Some of them will return multiple rows which causes the error. You can use WHERE/GROUP BY/PARTITION to avoid multiple rows.
SELECT ID FROM X_RPT_REPORTINGLIST
SELECT REPORT_NAME FROM X_RPT_REPORTINGLIST
SELECT STANDARD_REPORT FROM X_RPT_REPORTINGLIST
SELECT REPOPT_PACK_VERSION FROM X_RPT_REPORTINGLIST
SELECT PATH FROM ReportServer$PORTAL.dbo.Catalog
You can do it this way
INSERT [dbo].[X_RPT_PORTAL_REPORTLIST] ([PORTAL_GROUP_ID], [REPORT_DISPLAY_NAME], [STANDARD_REPORT], [REPORT_PACK_VERSION], [REPORT_PATH])
SELECT
a.ID, a.REPORT_NAME, a.STANDARD_REPORT, a.REPOPT_PACK_VERSION,
b.PATH
FROM
X_RPT_REPORTINGLIST a
JOIN
ReportServer$PORTAL.dbo.Catalog b ON XXXXXXX
Instead of XXXX you have to type the join condition for those two tables
the issue with the query is all the subqueries are returning more than 1 records.
i.e. :
(SELECT ID FROM X_RPT_REPORTINGLIST) line is returning more than 1 records, which is not permitted in INSERT statement.
you can use following code:
INSERT [dbo].[X_RPT_PORTAL_REPORTLIST]
([PORTAL_GROUP_ID], [REPORT_DISPLAY_NAME], [STANDARD_REPORT], [REPORT_PACK_VERSION], [REPORT_PATH])
VALUES (
(SELECT top 1 ID FROM X_RPT_REPORTINGLIST),
(SELECT top 1 REPORT_NAME FROM X_RPT_REPORTINGLIST),
(SELECT top 1 STANDARD_REPORT FROM X_RPT_REPORTINGLIST),
(SELECT top 1 REPOPT_PACK_VERSION FROM X_RPT_REPORTINGLIST),
(SELECT top 1 [PATH] FROM ReportServer$PORTAL.dbo.Catalog))
Note: changed the column name from PATH(which is a keyword ) to [PATH]
Try like this
INSERT INTO [dbo].[X_RPT_PORTAL_REPORTLIST]
([PORTAL_GROUP_ID], [REPORT_DISPLAY_NAME], [STANDARD_REPORT], [REPORT_PACK_VERSION], [REPORT_PATH])
SELECT rl.ID, rl.REPORT_NAME, rl.STANDARD_REPORT, rl.REPOPT_PACK_VERSION, c.PATH
FROM X_RPT_REPORTINGLIST rl
INNER JOIN ReportServer$PORTAL.dbo.Catalog c ON c.Name = rl.REPORT_NAME

I am trying to return a certain values in each row which depend on whether different values in that row are already in a different table

I'm still a n00b at SQL and am running into a snag. What I have is an initial selection of certain IDs into a temp table based upon certain conditions:
SELECT DISTINCT ID
INTO #TEMPTABLE
FROM ICC
WHERE ICC_Code = 1 AND ICC_State = 'CA'
Later in the query I SELECT a different and much longer listing of IDs along with other data from other tables. That SELECT is about 20 columns wide and is my result set. What I would like to be able to do is add an extra column to that result set with each value of that column either TRUE or FALSE. If the ID in the row is in #TEMPTABLE the value of the additional column should read TRUE. If not, FALSE. This way the added column will ready TRUE or FALSE on each row, depending on if the ID in each row is in #TEMPTABLE.
The second SELECT would be something like:
SELECT ID,
ColumnA,
ColumnB,
...
NEWCOLUMN
FROM ...
NEWCOLUMN's value for each row would depend on whether the ID in that row returned is in #TEMPTABLE.
Does anyone have any advice here?
Thank you,
Matt
If you left join to the #TEMPTABLE you'll get a NULL where the ID's don't exist
SELECT ID,
ColumnA,
ColumnB,
...
T.ID IS NOT NULL AS NEWCOLUMN -- Gives 1 or 0 or True/false as a bit
FROM ... X
LEFT JOIN #TEMPTABLE T
ON T.ID = X.ID -- DEFINE how the two rows can be related unquiley
You need to LEFT JOIN your results query to #TEMPTABLE ON ID, this will give you the ID if there is one and NULL if there isn't, if you want 1 or 0 this would do it (For SQL Server) ISNULL(#TEMPTABLE.ID,0)<>0.
A few notes on coding for performance:
By definition an ID column is unique so the DISTINCT is redundant and causes unnecisary processing (unless it is an ID from another table)
Why would you store this to a temporary table rather than just using it in the query directly?
You could use a union and a subquery.
Select . . . . , 'TRUE'
From . . .
Where ID in
(Select id FROM #temptable)
UNION
SELECT . . . , 'FALSE'
FROM . . .
WHERE ID NOT in
(Select id FROM #temptable)
So the top part, SELECT ... FROM ... WHERE ID IN (Subquery), does a SELECT if the ID is in your temptable.
The bottom part does a SELECT if the ID is not in the temptable.
The UNION operator joins the two results nicely, since both SELECT statements will return the same number of columns.
To expand on what someone else was saying with Union, just do something like so
SELECT id, TRUE AS myColumn FROM `table1`
UNION
SELECT id, FALSE AS myColumn FROM `table2`

Oracle SQL: Returning a Record even when a specific value doesn't exist

I have a query where I'm trying to pull some values from a table where a specific ID is queried for. If that value doesn't exist, I would still like the query to return a record that only has that ID value I was looking for. Here's what I've tried so far.
Select attr.attrval, attr.uidservicepoint, sp.servicepointid
From bilik.lssrvcptmarketattr attr
Join bilik.lsmarketattrtype type on attr.uidmarketattrtype = type.uidmarketattrtype AND
type.attrtype IN ('CAPACITY_REQUIREMENT_KW') and TO_CHAR( attr.starttime , 'mm/dd/yyyy')in ('05/01/2011')
Right Outer Join bilik.lsservicepoint sp on attr.uidservicepoint = sp.uidservicepoint
Where sp.servicepointid in ('RGE_R01000051574382') Order By sp.servicepointid ASC
In this example, I'm trying to look for RGE_R01000051574382. If that doesn't exist in table SP.servicepointid, I want it to still return the 'RGE_R01000051574382' in a record with nulls for the other values I'm pulling. Normally, when I'm running this, I will be pulling about 1000 specific values at a time.
If anyone has any insight that they can give on this, it would be greatly appreciated. Thanks so much!
If I understand correctly, you just need to move the WHERE clause into the JOIN clause.
select attr.attrval,
attr.uidservicepoint,
sp.servicepointid
from bilik.lssrvcptmarketattr attr
join bilik.lsmarketattrtype type on attr.uidmarketattrtype = type.uidmarketattrtype
and type.attrtype in ('CAPACITY_REQUIREMENT_KW')
and TO_CHAR(attr.starttime, 'mm/dd/yyyy') in ('05/01/2011')
right outer join bilik.lsservicepoint sp on attr.uidservicepoint = sp.uidservicepoint
and sp.servicepointid in ('RGE_R01000051574382')
order by sp.servicepointid
I think you're saying you want to have a record returned, with the servicepointid column populated, but all others null?
In that case, use a union.
select ...your query without order by...
and sp.servicepointid = 'RGE_R010000515743282'
union
select null, null, 'RGE_R010000515743282'
from dual
where not exists (select 'x' from (...your query without order by...))
Here's a complete example:
create table test (id number, val varchar2(10));
insert into test (id, val) values (1, 'hi');
select id,
val
from test
where id = 1
union
select 1,
null
from dual
where not exists (select 'x'
from test
where id = 1)