Dynamic SQL Select Variable Statement - sql

First time poster with beginner sql knowledge (so go easy on me)
I have a SQL statement currently that extracts monthly data from a table, im looking to make this extraction dynamic and rolling based on previous month.
For example - Assuming the date is 01/12/2013
Select Month10_Values
,Month11_Values
,Month12_Values
from test_table;
I want to replace the the numbers of the fields with a dynamic variable something like this:
Select Month[curr_month-2]_Values
,Month[curr_month-1]_Values
,Month[curr_month]_Values
from test_table;
Where [curr_month] will have been pre-determined (in this case 12 based on an assumed date of 01/12/2013)
Any help on this would be greatly appreciated, hopefully I've made some sense.
Thanks

You should do something like that (simplified)
declare
currMonth number:=12;
plsql_block VARCHAR2(500);
begin
plsql_block:='Select Month'||currMonth -2||'_Values,
Month'||curr_month-1||'_Values,
Month'||currMonth||'_Values
from test_table';
execute immediate plsql_block;
end
If you want to get the result of the dynamic statement, take a look here for example.

Related

How to use a table's content for querying other tables in BIgQuery

My team and I are using a query on a daily basis to receive specific results from a large dataset. This query is constantly updated with different terms that I would like to receive from the dataset.
To make this job more scaleable, I built a table of arrays, each containing the terms and conditions for the query. That way the query can lean on the table, and changes that I make in the table will affect the query without the need to change it.
The thing is - I can't seem to find a way to reference the table in the actual query without selecting it. I want to use the content of the table as a WHERE condition. for example:
table1:
terms
[term1, term2, term3]
query:
select * from dataset
where dataset.collumn like '%term1'
or dataset.collumn like '%term2'
or dataset.collumn like '%term3'
etc.
If you have any ideas please let me know (if the solution involves Python or JS this is also great)
thanks!
You can "build" the syntax you want using Procedural Language in BigQuery and then execute it. Here is a way of doing it without "leaving" BQ (meaning, without using external code):
BEGIN
DECLARE statement STRING DEFAULT 'SELECT col FROM dataset.table WHERE';
FOR record IN (SELECT * FROM UNNEST(['term1','term2','term3']) as term)
DO
SET statement = CONCAT(statement, ' col LIKE "', '%', record.term, '" OR');
END FOR;
SET statement = CONCAT(statement, ' 1=2');
EXECUTE IMMEDIATE statement;
END;

Replacing poor performing cursor in SQL

I've wrote a sql statement using cursor but unfortunately the performance is pretty poor.
The data set that I'm running it on is about 8m records.
The cursor using table with some regex expressions (around 100) to try to extract parts from the column data itself.
FOR cur_row AS r_cursor(x)
DO
SELECT SUBSTR_REGEXPR(cur_row.REGEX_PATTERN IN im_str GROUP cur_row.REGEX_GROUP) INTO col_part FROM DUMMY;
IF :col_part IS NOT NULL THEN
SELECT LTRIM(RTRIM(col_part)) FROM DUMMY; //some more assignments go there
BREAK;
ELSE
col_part = im_str;
END IF;
END FOR;
Unfortunately for those 8m records this take over 40min.
Does anyone have any idea how can I rewrite it? (I'm using SAP HANA)
Instead of using the reg ex for each row of the cursor, start with a smaller set of data of possible. Make your data set as small as possible using an initial filter.
I don't know SAP HANA syntax, but in pseudocode:
select records into temptable where field contains search criteria
for each row in temptable
do something

Oracle SQL use variable partition name

I run a daily report that has to query another table which is updated separately. Due to the high volume of records in the source table (8M+ per day) each day is stored in it's own partition. The partition has a standard format as P ... 4 digit year ... 2 digit month ... 2 digit date, so yesterday's partition is P20140907.
At the moment I use this expression, but have to manually change the name of the partition each day:
select * from <source_table> partition (P20140907) where ....
By using sysdate, toChar and Concat I have created another table called P_NAME2 that will automatically generate and update a string value as the name of the partition that I need to read. Now I need to update my main query so it does this:
select * from <source_table> partition (<string from P_NAME2>) where ....
You are working too hard. Oracle already does all these things for you. If you query the table using the correct date range oracle will perform the operation only on the relevant partitions - this is called pruning .
I suggest reading the docs on that.
If you'r still skeptic, Query all_tab_partitions.HIGH_VALUE to get each partitions high value (the table you created ... ).
I thought I'd pop back to share how I solved this in the end. The source database has a habit of leaking dates across partitions which is why queries for one day were going outside a single partition. I can't affect this, just work around it ...
begin
execute immediate
'create table LL_TEST as
select *
from SCHEMA.TABLE Partition(P'||TO_CHAR(sysdate,'YYYYMMDD')||')
where COLUMN_A=''Something''
and COLUMN_B=''Something Else''
';
end
;
Using the PL/SQL script I create the partition name with TO_CHAR(sysdate,'YYYYMMDD') and concatenate the rest of the query around it.
Note that the values you are searching for in the where clause require double apostrophes so to send 'Something' to the query you need ''Something'' in the script.
It may not be pretty, but it works on the database that I have to use.

TSQL: Returned value of a function is the name of the column

I have a function which using several cases to look up the current period returns a varchar(50) which is the period column necessary for what I need.
I would like to do a SUM of this column, and I'm not sure how to go about it.
Example:
Select SUM(ABS([dbo].[ACTUAL_PERIOD] ())) FROM Finance_DB
Any help would be great.
Also, do you think I should bother using the function in the first place? Basically all it does is work through 12 case statements that determines what period we are in by looking up another table. At first I was going to use a stored procedure, but duh...it won't return anything. The reason why I was going to use it was because this particular case statement appears repetitively throughout the entire query and all others. It gets long and I thought a procedure/function would look neater. However, having done some reading online, I understand that certain circumstances don't actually benefit from having functions as opposed to writing the query inline, how ever verbose it might be. Any thoughts?
In this case you should use a dynamic SQL.
For example:
declare #SQL nvarchar(100);
select #SQL='Select SUM(ABS('+[dbo].[ACTUAL_PERIOD]()+')) FROM Finance_DB';
execute sp_executesql #SQL;
If I understand your code correctly you got period values in different columns.
Period1 Period2 Period3...
100 200 400
130 250 300
Use unpivot to convert columns to rows so it looks like
ColumnName Value
Period1 100
Period2 200
Period3 400
...
The code will look something like
WITH Values AS (
SELECT ColumnName
,Value
FROM Finance_DB
UNPIVOT (Value FROM ColumnName IN (Period1, Period2,...)
)
SELECT SUM(ABS(Value))
FROM Values
WHERE ColumnName = Actual_Period();

SQL Server Stored Procedure - Use Row Count in Select query

My stored procedure (SQL Server 2005) returns a dataset where one field depends, among other things, on the number of rows returned by the query. I can make a simplified first query that allows me to get ##ROWCOUNT but, in that case, the procedure returns the two sets, which is not what I want.
I tried putting the first query in a WITH statement but haven't found the syntax to extract the row count and put it in a variable that I could use in the second query. An alternative would be to get ##ROWCOUNT from the first query and tell the procedure to return only the result of the second query.
There are probably better ways to do that but my expertise in SQL is quite limited...
Thanks for any help!
Is this what you're looking for? If not, could you please describe your problem in more details (perhaps, with code snippets)
alter procedure ComplicatedStoredProcedure as
begin
declare #lastQueryRowCount int
-- Storing the number of rows returned by the first query into a variable.
select #lastQueryRowCount =
-- First resultset (not seen by caller).
(select count(*) from A where ID > 100)
-- Second resultset. This will be the actual result returned from the SP.
select * from B where SomeDependentField > #lastQueryRowCount
end