Selecting columns from a stored Proc? - sql

I have a stored proc and I am trying to select all rows from it.
SELECT * FROM dbo.SEL_My_Func 'arg1','arg2','ar3'
didnt work. So I also tried:
SELECT * FROM EXEC dbo.SEL_My_Func 'arg1','arg2','ar3'
but this also didnt work. How do I get to test my stored proc returns correct results?
I have had to use a proc, rather than a function because I have an ORDER BY as part of the SQL, see: Selecting first row per group
Lastly, am I right in thinking there is no problem limiting which columns are returned from the stored probc, you just cant specify which rows (otherwise you would be better using a SQL function)?

The solution you are using qwill not work:
workarounds are there
SELECT a.[1], a.[2]
FROM OPENROWSET('SQLOLEDB','myserver';'sa';'mysapass',
'exec mydatabase.dbo.sp_onetwothree') AS a
or split your task in two queries
Declare #tablevar table(col1,..
insert into #tablevar(col1,..) exec MyStoredProc 'param1', 'param2'
SELECT col1, col2 FROM #tablevar

EXEC dbo.SEL_My_Func 'arg1','arg2','ar3'

Your assumption about functions is incorrect. You can use partition functions to select the first row in group.
Here is an example to find the first dealer_id for each client:
select client, dealer_id
from (
select client, dealer_guid
, RANK() over ( partition by client order by dealer_id) as rnk
from Dealers
) cd where rnk = 1
This can also be done with a function call as well as with a table (my example).

Related

Teradata: IN clause in Pivot can't take data from Table

I wish to extract a few Calender Weeks from an yearly data. Once that's done, I want to pivot it, so that there is one row for each ID.
We have a table DB.MY_CWs having just one column CW containing the Calender Weeks we are interested in.
The following code extracts the relevant Calender Weeks.
CREATE TABLE DB.MY_TABLE AS
(
SELECT ID,
WeekNumber_Of_Year(Sales_Date)) AS CW,
AVG(Sales) AS Sales
FROM DB.DataBase_XYZ
WHERE CW IN (SELECT CW FROM DB.MY_CWs)
GROUP BY ID,CW
) WITH DATA;
This Code gives us the output like this:
But, I would like to pivot it so that I get an output like this:
I took the help from code here and ran the following, but TeraData doesn't respond and there is no Error either.
CREATE TABLE DB.MY_TABLE2 AS
(
SELECT *
FROM DB.MY_TABLE
PIVOT
(SUM(Sales) AS Sales
FOR CW IN (SELECT CW FROM DB.MY_CWs)
) AS dt
) WITH DATA;
If instead of (SELECT CW FROM DB.MY_CWs) I would have used (15,16,17), then everything works fine and I would have got the pivoted Table, as shown above.
Can anyone suggest where I am making the mistake?
Many thanks.
I tried to recreate the scenario.
I am getting below error.
CREATE TABLE Failed. 4306: (-4306)Invalid PIVOT query: PIVOT query with sub-query in IN-List is not supported in DDL statement.
There are few limitation while using subquery in pivot table.
TD Documentation:
https://docs.teradata.com/r/Teradata-VantageTM-NewSQL-Engine-Release-Summary/March-2019/Release-16.20-Feature-Update-1-Features/Subquery-Support-in-PIVOT-IN-List
Snippet from TD Documentation
Considerations
PIVOT with a subquery in the IN-list is not supported in a multistatement request. PIVOT columns are decided dynamically at the optimization phase. Because of this dynamic behavior, the following are usage considerations of a PIVOT query with a subquery in the IN-list.
Not supported in DDL creation statements.
Not supported in stored procedure's cursor FETCH statement.
SET operations are not allowed on a PIVOT query if subquery is given in the IN-list.
Resultant PIVOT column names cannot be explicitly specified in the SELECT list.
Does not support ORDER BY clause.
If you are using SQL Assistant, kindly check your history for the error details.
Otherwise you can query dbc.dbqlogtbl to check the errortext.
Workaround:
You can achieve the desired output through Dynamic SQL and Stored Procedure.
Steps:
Convert the output of the subquery to a String. We can do that through XMLAGG.
Concatenate the Step1 output in the IN Clause and execute the dynamically generated SQL.
REPLACE PROCEDURE DYNAMIC_PIVOT()
BEGIN
DECLARE Sqltxt VARCHAR(1000);
DECLARE CWtxt VARCHAR(250);
--Convert rows from MY_CWs to comma delimited string
SET CWtxt=(SELECT TRIM( TRAILING ',' FROM ( XMLAGG(CAST(CW AS VARCHAR(10))||',') (VARCHAR(255)) ) ) FROM MY_CWs);
SET Sqltxt=('CREATE TABLE MY_TABLE2 AS
(
SELECT *
FROM MY_TABLE
PIVOT
(SUM(Sales) AS Sales
FOR CW IN ('|| CWtxt ||')
) AS dt
) WITH DATA;') ;
CALL DBC.SYSEXECSQL(Sqltxt);
END;
CALL DYNAMIC_PIVOT();

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

Get count and result from SQL query in Go

I'm running a pretty straightforward query using the database/sql and lib/pq (postgres) packages and I want to toss the results of some of the fields into a slice, but I need to know how big to make the slice.
The only solution I can find is to do another query that is just SELECT COUNT(*) FROM tableName;.
Is there a way to both get the result of the query AND the count of returned rows in one query?
Conceptually, the problem is that the database cursor may not be enumerated to the end so the database does not really know how many records you will get before you actually read all of them. The only way to count (in general case) is to go through all the records in the resultset.
But practically, you can enforce it to do so by using subqueries like
select *, (select count(*) from table) from table
and just ignore the second column for records other than first. But it is very rude and I do not recommend doing so.
Not sure if this is what you are asking for but you can call the ##Rowcount function to return the count of the previous select statement that has been executed.
SELECT mytable.mycol FROM mytable WHERE mytable.foo = 'bar'
SELECT ##Rowcount
If you want the row count included in your result set you can use the the OVER clause (MSDN)
SELECT mytable.mycol, count(*) OVER(PARTITION BY mytable.foo) AS 'Count' FROM mytable WHERE mytable.foo = 'bar'
You could also perhaps just separate two SQL statements with the a ; . This would return a result set of both statements executed.
You would used count(*)
SELECT count(distinct last)
FROM (XYZTable)
WHERE date(FROM_UNIXTIME(time)) >= '2013-10-28' AND
id = 90 ;

Using output from "with as" few times

I can't use t from
with t as (
select row_number() OVER (partition by ID ORDER BY id) as numb, *
from my_table
where id= 6
)
select top 2 from t # it works
select top 2 from t # here I get error Invalid object name 't'.
Is there any tip to use t more than on time?
You cannot do this. CTEs can only be used in one statement (though you can use it multiple times within one statement.
Take a look at this article. Snippit:
Once a CTE is defined, it can be
referenced multiple times by the first
query that follows it.
And from their documentation:
A common table expression (CTE) can be
thought of as a temporary result set
that is defined within the execution
scope of a single SELECT, INSERT,
UPDATE, DELETE, or CREATE VIEW
statement.
Emphasis on, "scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement."
Is there any tip to use t more than on time?
Sure, if you are doing this in a stored proc, just dump it into a #temp table. At the end of the stored proc, the #temp table disappears.
with t as (
select row_number() OVER (partition by ID ORDER BY id) as numb, *
from my_table
where id= 6
)
select * into #tmp from t
select top 2 from #tmp -- good
select top 2 from #tmp -- good also
Outside of SP, just make sure you drop the #table before you attempt to create it again, otherwise the next select ..into #name will error out with #name already exists
You can use a CTE only in a single query that follows the CTE. You can however make the query that follows as complicated as you wish.
In your example, you might consider a union between the 2 selects depending on precisely what you want. The code you gave isn't descriptive enough for me to suggest any other variants.

SQLServer SQL query with a row counter

I have a SQL query, that returns a set of rows:
SELECT id, name FROM users where group = 2
I need to also include a column that has an incrementing integer value, so the first row needs to have a 1 in the counter column, the second a 2, the third a 3 etc
The query shown here is just a simplified example, in reality the query could be arbitrarily complex, with several joins and nested queries.
I know this could be achieved using a temporary table with an autonumber field, but is there a way of doing it within the query itself ?
For starters, something along the lines of:
SELECT my_first_column, my_second_column,
ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter
FROM my_table
However, it's important to note that the ROW_NUMBER() OVER (ORDER BY ...) construct only determines the values of Row_Counter, it doesn't guarantee the ordering of the results.
Unless the SELECT itself has an explicit ORDER BY clause, the results could be returned in any order, dependent on how SQL Server decides to optimise the query. (See this article for more info.)
The only way to guarantee that the results will always be returned in Row_Counter order is to apply exactly the same ordering to both the SELECT and the ROW_NUMBER():
SELECT my_first_column, my_second_column,
ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter
FROM my_table
ORDER BY my_order_column -- exact copy of the ordering used for Row_Counter
The above pattern will always return results in the correct order and works well for simple queries, but what about an "arbitrarily complex" query with perhaps dozens of expressions in the ORDER BY clause? In those situations I prefer something like this instead:
SELECT t.*
FROM
(
SELECT my_first_column, my_second_column,
ROW_NUMBER() OVER (ORDER BY ...) AS Row_Counter -- complex ordering
FROM my_table
) AS t
ORDER BY t.Row_Counter
Using a nested query means that there's no need to duplicate the complicated ORDER BY clause, which means less clutter and easier maintenance. The outer ORDER BY t.Row_Counter also makes the intent of the query much clearer to your fellow developers.
In SQL Server 2005 and up, you can use the ROW_NUMBER() function, which has options for the sort order and the groups over which the counts are done (and reset).
The simplest way is to use a variable row counter. However it would be two actual SQL commands. One to set the variable, and then the query as follows:
SET #n=0;
SELECT #n:=#n+1, a.* FROM tablename a
Your query can be as complex as you like with joins etc. I usually make this a stored procedure. You can have all kinds of fun with the variable, even use it to calculate against field values. The key is the :=
Heres a different approach.
If you have several tables of data that are not joinable, or you for some reason dont want to count all the rows at the same time but you still want them to be part off the same rowcount, you can create a table that does the job for you.
Example:
create table #test (
rowcounter int identity,
invoicenumber varchar(30)
)
insert into #test(invoicenumber) select [column] from [Table1]
insert into #test(invoicenumber) select [column] from [Table2]
insert into #test(invoicenumber) select [column] from [Table3]
select * from #test
drop table #test