SQL complex unions - sql

This is a little tricky to describe, but hopefully there is a solution.
I have a UDF which takes an ID and returns a table. Is there a way I can do a SELECT for these IDs and perform a UNION of the UDF results? For example;
To get the IDs;
SELECT [ID]
FROM [TableOfIDs]
To get the object properties from an ID;
SELECT *
FROM GetObjectProperties(#ID)
But how do I combine the two? That is, to do a union of the UDF results from a query for the IDs?
I hope that makes sense!

You need to use APPLY:
SELECT TT.*
FROM [TableOfIDs] AS T CROSS APPLY GetObjectProperties(T.ID) AS TT;

Related

Testing the max() functions in SQL (Teradata) without having to query a database

This is probably a simple one, but I'm not able to find it anywhere. I just want to check what the MAX() function in a Teradata SQL query would return, using a list of strings. I have a Teradata database I'm working with, but I don't have a table to query (I need to know the output of MAX() before I can populate the table data). I'm using Aqua Data Studio.
I tried
select max('test1','untest2','_test3')
and I also tried
select max(field_name) where field_name in ('test1','untest2','_test3')
but both throw an error.
What am I missing?
Shouldn't that be the GREATEST function instead?
select greatest('test1','untest2','_test3')
Does this work for you?
select max(field_name)
from
(
select 'test1' as field_name union
select 'untest2' as field_name union
select '_test3' as field_name
) tbl
try providing data via VALUES or UNNEST(array)
SELECT max(x) FROM (
VALUES ('test1'),('untest2'),('_test3')
) AS x(x)
or
SELECT max(x) FROM
UNNEST(ARRAY['test1','untest2','_test3']) AS x

How to stack two columns into rows in a single column?

I have following table named 'model', I want sql server code to achieve the result.
My desired output should be as follows,
Any help would be appreciated.
You can try this - just another simple way :)
SELECT ModelA, Discount
from table1
UNION
SELECT ModelB, Discount
from table1
I like to use apply for this purpose:
select v.model, t.discount
from t cross apply
(values (model1), (model2)) v(model);
apply is a very powerful construct that implements something called "lateral joins". There are other methods to unpivot such data, but I unpivoting is a good introduction to lateral joins.
It's UNION ALL that you need:
select modela as model, discount from model
union all
select modelb, discount from model

counting rows in select clause with DB2

I would like to query a DB2 table and get all the results of a query in addition to all of the rows returned by the select statement in a separate column.
E.g., if the table contains columns 'id' and 'user_id', assuming 100 rows, the result of the query would appear in this format: (id) | (user_id) | 100.
I do not wish to use a 'group by' clause in the query. (Just in case you are confused about what i am asking) Also, I could not find an example here: http://mysite.verizon.net/Graeme_Birchall/cookbook/DB2V97CK.PDF.
Also, if there is a more efficient way of getting both these results (values + count), I would welcome any ideas. My environment uses zend framework 1.x, which does not have an ODBC adapter for DB2. (See issue http://framework.zend.com/issues/browse/ZF-905.)
If I understand what you are asking for, then the answer should be
select t.*, g.tally
from mytable t,
(select count(*) as tally
from mytable
) as g;
If this is not what you want, then please give an actual example of desired output, supposing there are 3 to 5 records, so that we can see exactly what you want.
You would use window/analytic functions for this:
select t.*, count(*) over() as NumRows
from table t;
This will work for whatever kind of query you have.

How to refer to a variable create in the course of executing a query in T-SQL, in the WHERE clause?

What the title says, really.
If I SELECT [statement] AS whatever, why can't I refer to the whatever column in the body of the WHERE clause? Is there some kind of a workaround? It's driving me crazy.
As far as I'm aware, you can't directly do this in SQL Server.
If you REALLY have to use your column alias in the WHERE clause, you can do this, but it seems like overkill to use a subquery just for the alias:
SELECT *
FROM
(
SELECT [YourColumn] AS YourAlias, etc...
FROM Whatever
) YourSubquery
WHERE YourAlias > 2
You're almost certainly better off just using the contents of the original column in your WHERE clause.
It has to do with the way a SELECT statement gets translated into an abstract query tree: the 'whatever' only appears in the query result projection part of the tree, which is above the filtering part of the tree, so the WHERE clause cannot understand the 'whatever'. This is not some internal implementation detail, it is a fundamental behavior of relational queries: the projection of the result occurs after the evaluation of the joins and filters.
IS really trivial to work around the 'problem' by making the hierarchy of the query explicit:
select ...
from (
select [something] as whatever
from ...
) as subquery
WHERE whatever = ...;
A common table expression can also server the same purpose:
with cte as (
select [something] as whatever
from ...)
select ... from cte
WHERE whatever = ...;
It's to do with the order of operations in the select statement. The WHERE clause is evaluated before the SELECT clause so this information isn't available. Although it is available in the ORDER BY clause as this is processed last.
As others have mentioned, a sub-query will get around this problem.

SQL select from data in query where this data is not already in the database?

I want to check my database for records that I already have recorded before making a web service call.
Here is what I imagine the query to look like, I just can't seem to figure out the syntax.
SELECT *
FROM (1,2,3,4) as temp_table
WHERE temp_table.id
LEFT JOIN table ON id IS NULL
Is there a way to do this? What is a query like this called?
I want to pass in a list of id's to mysql and i want it to spit out the id's that are not already in the database?
Use:
SELECT x.id
FROM (SELECT #param_1 AS id
FROM DUAL
UNION ALL
SELECT #param_2
FROM DUAL
UNION ALL
SELECT #param_3
FROM DUAL
UNION ALL
SELECT #param_4
FROM DUAL) x
LEFT JOIN TABLE t ON t.id = x.id
WHERE x.id IS NULL
If you need to support a varying number of parameters, you can either use:
a temporary table to populate & join to
MySQL's Prepared Statements to dynamically construct the UNION ALL statement
To confirm I've understood correctly, you want to pass in a list of numbers and see which of those numbers isn't present in the existing table? In effect:
SELECT Item
FROM IDList I
LEFT JOIN TABLE T ON I.Item=T.ID
WHERE T.ID IS NULL
You look like you're OK with building this query on the fly, in which case you can do this with a numbers / tally table by changing the above into
SELECT Number
FROM (SELECT Number FROM Numbers WHERE Number IN (1,2,3,4)) I
LEFT JOIN TABLE T ON I.Number=T.ID
WHERE T.ID IS NULL
This is relatively prone to SQL Injection attacks though because of the way the query is being built. It'd be better if you could pass in '1,2,3,4' as a string and split it into sections to generate your numbers list to join against in a safer way - for an example of how to do that, see http://www.sqlteam.com/article/parsing-csv-values-into-multiple-rows
All of this presumes you've got a numbers / tally table in your database, but they're sufficiently useful in general that I'd strongly recommend you do.
SELECT * FROM table where id NOT IN (1,2,3,4)
I would probably just do:
SELECT id
FROM table
WHERE id IN (1,2,3,4);
And then process the list of results, removing any returned by the query from your list of "records to submit".
How about a nested query? This may work. If not, it may get you in the right direction.
SELECT * FROM table WHERE id NOT IN (
SELECT id FROM table WHERE 1
);