Creating a table from two queries, error with "WITH" clause - sql-server-2008

Good Morning!
I am trying to combine two queries to make a table. (Please see code below)
`CREATE TABLE Layer_Loss
(
dYear INT NOT NULL,
EventNum INT NOT NULL,
Loss INT NULL,
Rec_L1 BIGINT NULL,
Rec_L2 BIGINT NULL,
Rec_L3 BIGINT NULL,
Cap_CML_L1 BIGINT NULL,
Cap_CML_L2 BIGINT NULL,
Cap_CML_L3 BIGINT NULL,
)
INSERT INTO Layer_Loss (dYear,EventNum, Loss, Rec_L1, Rec_L2, Rec_L3, Capped_CML_L1, Capped_CML_L2, Capped_CML_L3)
WITH c AS (SELECT Row_number() OVER (ORDER BY dYear) AS rownum,*
FROM Layer_Loss_Capped2)
SELECT *
FROM
(
SELECT dYear, ROW_NUMBER() OVER (Partition by dYear Order by dYear) as Event_Number, Loss
, 'Recovery_L1'=CASE
WHEN Loss<10000000 THEN 0
WHEN Loss<30000000 THEN 20000000-(30000000-Loss)
ELSE 20000000
END
, 'Recovery_L2'=CASE
WHEN Loss<30000000 THEN 0
WHEN Loss<60000000 THEN 30000000-(60000000-Loss)
ELSE 30000000
END
, 'Recovery_L3'=CASE
WHEN Loss<60000000 THEN 0
WHEN Loss<100000000 THEN 40000000-(100000000-Loss)
ELSE 40000000
END
, (SELECT *, 'Capped_CML_L1'=CASE
WHEN d.CML_L1>40000000 THEN 4000000
ELSE d.CML_L1
END
, (SELECT *, 'Capped_CML_L2'=CASE
WHEN d.CML_L2>60000000 THEN 6000000
ELSE d.CML_L1
END
, (SELECT *, 'Capped_CML_L3'=CASE
WHEN d.CML_L1>80000000 THEN 8000000
ELSE d.CML_L1
END
FROM
(
SELECT a.dYear, a.EventNum, a.Loss, a.Rec_L1, SUM(b.Rec_L1) AS CML_L1, SUM(b.Rec_L2) AS CML_L2, SUM(b.Rec_L3) as CML_L3
FROM c a
LEFT JOIN c b ON a.dYear = b.dYear AND b.rownum <= a.rownum
GROUP BY a.dYear, a.rownum, a.EventNum, a.Rec_L1, a.Loss
) AS d
) AS e
FROM ['04_AIR_StdHU_DS_noSS_ByTerr$']
) AS a
DROP TABLE Layer_Loss`
I have it so that the query about 'Recovery_L1', 'Recovery_L2', and 'Recovery_L3' are about of table "Layer_Loss", which I've called "Rec_L1", "Rec_L2", and "Rec_L3". When I try to add the query that leads to "Capped_CML_L1", "Capped_CML_L2", and "Capped_CML_L3" I get the following error:
"Msg 156, Level 15, State 1, Line 14
Incorrect syntax near the keyword 'WITH'.
Msg 319, Level 15, State 1, Line 14
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon."
I have tried moving 'WITH' clause around but end up with the same result.
Also, this is not my end result. My next step would be to subtract the current row from the previous row from the columns "Capped_CML_L1", "Capped_CML_L2", and "Capped_CML_L3" into a column called "Inc_Rec_L1", "Inc_Rec_L2", and "Inc_Rec_L3". I was thinking about using a cursor, but I have never used one before, so if you have any suggestions on this, that would be great too!
Thank you for your help!
EDIT:
`CREATE TABLE Layer_Loss
(
dYear INT NOT NULL,
EventNum INT NOT NULL,
Loss INT NULL,
Rec_L1 BIGINT NULL,
Rec_L2 BIGINT NULL,
Rec_L3 BIGINT NULL,
Cap_CML_L1 BIGINT NULL,
Cap_CML_L2 BIGINT NULL,
Cap_CML_L3 BIGINT NULL,
)
;WITH c AS (SELECT Row_number() OVER (ORDER BY dYear) AS rownum,*
FROM Layer_Loss_Capped2)
INSERT INTO Layer_Loss (dYear,EventNum, Loss, Rec_L1, Rec_L2, Rec_L3, Capped_CML_L1, Capped_CML_L2, Capped_CML_L3)
SELECT *
FROM
(
SELECT dYear, ROW_NUMBER() OVER (Partition by dYear Order by dYear) as Event_Number, Loss
, 'Recovery_L1'=CASE
WHEN Loss<10000000 THEN 0
WHEN Loss<30000000 THEN 20000000-(30000000-Loss)
ELSE 20000000
END
, 'Recovery_L2'=CASE
WHEN Loss<30000000 THEN 0
WHEN Loss<60000000 THEN 30000000-(60000000-Loss)
ELSE 30000000
END
, 'Recovery_L3'=CASE
WHEN Loss<60000000 THEN 0
WHEN Loss<100000000 THEN 40000000-(100000000-Loss)
ELSE 40000000
END
, (SELECT *, 'Capped_CML_L1'=CASE
WHEN d.CML_L1>40000000 THEN 4000000
ELSE d.CML_L1
END
, (SELECT *, 'Capped_CML_L2'=CASE
WHEN d.CML_L2>60000000 THEN 6000000
ELSE d.CML_L1
END
, (SELECT *, 'Capped_CML_L3'=CASE
WHEN d.CML_L1>80000000 THEN 8000000
ELSE d.CML_L1
END
FROM
(
SELECT a.dYear, a.EventNum, a.Loss, a.Rec_L1, SUM(b.Rec_L1) AS CML_L1, SUM(b.Rec_L2) AS CML_L2, SUM(b.Rec_L3) as CML_L3
FROM c a
LEFT JOIN c b ON a.dYear = b.dYear AND b.rownum <= a.rownum
GROUP BY a.dYear, a.rownum, a.EventNum, a.Rec_L1, a.Loss
) AS d
FROM ['04_AIR_StdHU_DS_noSS_ByTerr$']
) AS e
) AS f
) AS g
) AS a
DROP TABLE Layer_Loss`
When I put in the above edited code I get error:
Msg 156, Level 15, State 1, Line 58
Incorrect syntax near the keyword 'FROM'.
I would like to be able to reference Capped_CML_L1, Capped_CML_L2, and Capped_CML_L3 in another query or table or cursor later on. I wanted it to be under just 'e' but I'm not sure how with the parentheses

WITH must be separated from any preceding command by a ;.
When a CTE is used in a statement that is part of a batch, the statement before it must be followed by a semicolon.
Also, it must be the first part of the entire statement it's a part of, whether that be a plain SELECT or an INSERT. Try:
/* CREATE TABLE */
;WITH c AS (SELECT Row_number() OVER (ORDER BY dYear) AS rownum,*
FROM Layer_Loss_Capped2)
INSERT INTO Layer_Loss (dYear,EventNum, Loss, Rec_L1, Rec_L2, Rec_L3,
Capped_CML_L1, Capped_CML_L2, Capped_CML_L3)
SELECT *
FROM
(
SELECT dYear, ROW_NUMBER() OVER ...
(Have also moved the WITH before the INSERT, having realised what was being attempted)
See also Transact SQL Syntax conventions:
; Transact-SQL statement terminator.Although the semicolon is not required for most statements in this version of SQL Server, it will be required in a future version.
One of the main reasons for this is that there is a pre-existing use for the keyword WITH that modifies SELECT statements. By insisting on the ;, it makes the parse a lot easier.

Related

Teradata SQL Split Single String into Table Rows

I have one string element, for example : "(1111, Tem1), (0000, Tem2)" and hope to generate a data table such as
var1
var2
1111
Tem1
0000
Tem2
This is my code, I created the lag token and filter with odd rows element.
with var_ as (
select '(1111, Tem1), (0000, Tem2)' as pattern_
)
select tbb1.*, tbb2.result_string as result_string_previous
from(
select tb1.*,
min(token) over(partition by 1 order by token asc rows between 1 preceding and 1 preceding) as min_token
from
table (
strtok_split_to_table(1, var_.pattern_, '(), ')
returns (outkey INTEGER, token INTEGER, result_string varchar(20))
) as tb1) tbb1
inner join (select min_token, result_string from tbb1) tbb2
on tbb1.token = tbb2.min_token
where (token mod 2) = 0;
But it seems that i can't generate new variables in "from" step and applied it directly in "join" step.
so I wanna ask is still possible to get the result what i want in my procedure? or is there any suggestion?
Thanks for all your assistance.
I wouldn't split / recombine the groups. Split each group to a row, then split the values within the row, e.g.
with var_ as (
select '(1111, Tem1), (0000, Tem2)' as pattern_
),
split1 as (
select trim(leading '(' from result_string) as string_
from
table ( /* split at & remove right parenthesis */
regexp_split_to_table(1, var_.pattern_, '\)((, )|$)','c')
returns (outkey INTEGER, token_nbr INTEGER, result_string varchar(256))
) as tb1
)
select *
from table(
csvld(split1.string_, ',', '"')
returns (var1 VARCHAR(16), var2 VARCHAR(16))
) as tb2
;

SSIS Package -Count based on multiple columns

I need to create an SSIS Package that provides me the count of workdoneby (contractor/company).
Input table from sql server db:
I need to count no of orders by contractor and company for a particular day + station + worktype + accountno.
My output should look like this.
Can someone help me how to create a package to get the desired output?
Since the data is in a table, you can ask the database engine to do the calculation logic.
Setup
I created a temporary table and populated it with the supplied data.
CREATE TABLE
#Source
(
[Date] date
, Station char(3)
, worktype char(2)
, Accountno varchar(10)
, workdoneby varchar(10)
)
INSERT INTO
#Source
(
Date
, Station
, worktype
, Accountno
, workdoneby
)
VALUES
('2018-06-24', 'RMS', 'RH', 'I.145.001', 'Company')
, ('2018-06-24', 'RMS', 'PH', 'I.145.001', 'Contractor')
, ('2018-06-24', 'RMS', 'PH', 'I.145.002', 'Company')
, ('2018-06-24', 'RMS', 'PH', 'I.145.002', 'Contractor');
Query time
Now let's query! I find it is helpful to break these problems down into smaller pieces. The first thing I want to do is break out the workdoneby column into two columns with a 1 or 0
SELECT
S.Date
, S.Station
, S.worktype
, S.Accountno
, CASE S.workdoneby
WHEN 'Contractor' THEN 1
ELSE 0
END AS contractorCount
, CASE S.workdoneby
WHEN 'Company' THEN 1
ELSE 0
END AS companyCount
FROM
#Source AS S
Running that let's me look at the results and see I still have 4 rows and I get the correct entity counted.
The next step is to collapse/summarize/roll-up the values. You indicate we should group by date/station/worktype/accountno so that's exactly what we're going to to do.
I find it easier to debug if I take that first query and make it a derived table so the basic form now becomes SELECT * FROM (ORIGINAL QUERY HERE) AS D thus
SELECT
D.Date
, D.Station
, D.worktype
, D.Accountno
, D.contractorCount
, D.companyCount
FROM
(
SELECT
S.Date
, S.Station
, S.worktype
, S.Accountno
, CASE S.workdoneby
WHEN 'Contractor' THEN 1
ELSE 0
END AS contractorCount
, CASE S.workdoneby
WHEN 'Company' THEN 1
ELSE 0
END AS companyCount
FROM
#Source AS S
) D
Now that you can see it's giving the same original results, we're going to use the SUM function on the contractorCount and companyCount columns and GROUP BY date/station/worktype/accountno
SELECT
D.Date
, D.Station
, D.worktype
, D.Accountno
, SUM(D.contractorCount) AS contractor
, SUM(D.companyCount) AS company
FROM
(
SELECT
S.Date
, S.Station
, S.worktype
, S.Accountno
, CASE S.workdoneby
WHEN 'Contractor' THEN 1
ELSE 0
END AS contractorCount
, CASE S.workdoneby
WHEN 'Company' THEN 1
ELSE 0
END AS companyCount
FROM
#Source AS S
) D
GROUP BY
D.Date
, D.Station
, D.worktype
, D.Accountno;
SSIS
Now that we have data looking as expected, within SSIS you need to do something with it. Your question doesn't specify what you need to do but likely you're going to use a Data Flow Task to push this aggregated data from one place to another destination (different server, Excel, etc) or you're going to push this data into a table on the same server in which case you're going to use an Execute SQL Task

mysql union all when creating views

I have the following code, if i run the code as an sql script it works but if i want to create a view from it i got this error: 1166 - Incorrect Column Name ''
select `c`.`package_id` AS `package_id`,
`c`.`student_id` AS `student_id`,
`bs`.`name` AS `stud_name`,
`c`.`payed_date` AS `payed_date`,
(case `c`.`type` when 'e' then 'Vizsgadíj' when 'c' then 'Tanfolyam díj' else '' end) AS `name`,
`c`.`course_price` AS `price`,
`c`.`pay_form` AS `pay_form`,
`c`.`venue_id` AS `venue_id`
from (`bma_student_pays` `c`
join `bma_students` `bs` on((`bs`.`id` = `c`.`student_id`)))
union all
select '0' AS `0`,'0' AS `0`,'' AS ``,`e`.`making_date` AS `making_date`,`e`.`name` AS `name`,`e`.`price` AS `price`,`e`.`type` AS `type`,`e`.`venue_id` AS `venue_id`
from `bma_extra_makings` `e`
union all
select '','','',i.inv_due,i.inv_name,i.inv_amount,i.`mode`,i.venue_id
from bma_invoices i
where i.inv_type='K'
Any help would really good.
Thanks!
In your second query (first UNION ALL), you have as your third column:
'' AS ``
This is not valid - remove the AS clause and all should be well.

issue while trying to insert one table into another one

I have a mysql table of 1.5 million record in a temproary table that I want to insert it into the main table with an inner join.
My code works but it stops at 103,613 records. IT does not keep going. Why would it stops? why it is not going all the way to the end?
This is my current code
INSERT INTO phone_calls(next_attempt, created_on, modified_on, status, call_subject,
account_number, call_code, last_attempt_on, total_attempts, account_id
,team_id
,campaign_id
,call_code_id
,result_code
,result_code_id
,time_zone_id
,trigger_on
,first_attempt_on
,first_attempt_by
,last_attempt_by
,modified_by
,client_id
,last_call_id
,call_notes
,owner_id
,industry_id
)
SELECT
CASE WHEN next_attempt IS NULL OR next_attempt = '' THEN STR_TO_DATE(replace(t.next_attempt,'/',','),'%m,%d,%Y %T') END as next_attempt,
CASE WHEN t.created_on IS NULL OR t.created_on = '' THEN '0000-00-00 00:00:00' ELSE STR_TO_DATE(replace(t.created_on,'/',','),'%m,%d,%Y %T') END as created_on,
CASE WHEN t.modified_on IS NULL OR t.modified_on = '' THEN '0000-00-00 00:00:00' ELSE STR_TO_DATE(replace(t.modified_on,'/',','),'%m,%d,%Y %T') END AS modified_on,
CONVERT( CASE WHEN t.status IS NULL OR t.status = '' THEN 0 ELSE t.status END, UNSIGNED INTEGER) AS status,
LEFT(IFNULL(t.call_subject, ''), 100),
t.account_number,
CONVERT( CASE WHEN t.callcode IS NULL OR t.callcode = '' THEN 0 ELSE t.callcode END , UNSIGNED INTEGER) AS callcode, STR_TO_DATE(replace(t.last_attempt_on,'/',','),'%m,%d,%Y %T') as last_attempt_on,
CONVERT( CASE WHEN t.New_Attempts IS NULL OR t.New_Attempts = '' THEN 0 ELSE t.New_Attempts END , UNSIGNED INTEGER) AS New_Attempts,
a.account_id
,0
,0
,0
,0
,0
,0
, '0000-00-00 00:00:00'
, '0000-00-00 00:00:00'
,1
,1
,1
,1
,0
,'IMPORTED FROM CRM'
,1
,1
FROM tmp_table_for_rdi_cms AS t
INNER JOIN accounts AS a ON a.account_number = t.account_number LIMIT 9999999999;
these 2 fields are indexed so it runs fast
a.account_number
t.account_number
Now, I know i am inserting no value for some fields that has a type if unsigned integer but that is okay as i will be updating this at later time.
How can i execute this INSERT INTO query without losing any record?
The "doesnt have a default value" problem is that the source table has nulls for columns on the new table that are defined S NOT NULL and which are not defined with a default value.
You have three choices to fix this:
Define the target columns as null able (leave out the NOT NULL)
Define the target columns with a default value, ie NOT NULL DEFAULT 'some value'
Provide a value if the column is null, ie SELECT ifnull(source_column, 'some value)
The Truncated incorrect INTEGER value problems and you are selecting from a char value and putting it in an int column, but some vyes are blank, so you need to handle that:
select if(source_column = '', 0, source_column)
The Data truncated for column problem is there because the source value is larger/longer than the target column can accommodate. To fix, define your target column to be larger (bigint instead of int) or longer (eg text or varchar(80) instead of varchar(20))

MySQL error - "check syntax to use near '%s"

Anyone see why the query below would yield the error
"#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%s)"?
SELECT SQL_CALC_FOUND_ROWS id
FROM (
SELECT taba.id
FROM (
SELECT alum.id
FROM cvm_education AS edu
JOIN cvm_alumni AS alum ON alum.id = edu.alumni_id
WHERE cvm_alumni.profile_status =1
AND highest_edu
IN (
SELECT name
FROM cvm_filter_educationlevels
JOIN cvm_educationlevel AS edulevels ON educationlevel_id = edulevels.id
WHERE filter_id = % s
)
) AS taba
Cheers!
you need to quote the string value and use LIKE for pattern matching
WHERE filter_id LIKE '% s'
but if you really want to find % s literally, use =
WHERE filter_id = '% s'
Try this:
SELECT count(taba.id)
FROM (
SELECT alum.id
FROM cvm_education AS edu
JOIN cvm_alumni AS alum ON alum.id = edu.alumni_id
WHERE alum.profile_status =1
AND highest_edu
IN (
SELECT name
FROM cvm_filter_educationlevels
JOIN cvm_educationlevel AS edulevels ON educationlevel_id = edulevels.id
WHERE filter_id = 1
)
) AS taba ;
http://www.sqlfiddle.com/#!2/f8adc/15
Two important points:
I don't understand the use of SQL_CALC_FOUND_ROWS() if have chanced
it in count(). I think this provides the same desired result.
You haven't provided sample data so I wasn't able to try %s. I have
substituted it with a binary (1,0). Furthermore, I don't know your
exact code so I made some assumptions based on your query.
Sample data:
CREATE TABLE cvm_education(
ID int auto_increment primary key,
alumni_id int
);
CREATE TABLE cvm_alumni(
ID int auto_increment primary key,
profile_status int,
highest_edu varchar(30)
);
CREATE TABLE cvm_filter_educationlevels (
ID int auto_increment primary key,
educationlevel_id int,
name varchar(30)
);
CREATE TABLE cvm_educationlevel(
ID int auto_increment primary key,
filter_id int
);
INSERT INTO cvm_education (alumni_id)
VALUES (10), (1), (2), (3),(5), (6),(7),(8),(9);
INSERT INTO cvm_alumni (profile_status, highest_edu)
VALUES (1, "master"),
(0,"bachelor"),
(1,"bachelor"),
(0, "master"),
(1, "master"),
(0, "master"),
(1, "master"),
(1, "master"),
(1, "master"),
(1, "master");
INSERT INTO cvm_filter_educationlevels(educationlevel_id,name)
VALUES (1, "master"), (0,"bachelor");
INSERT INTO cvm_educationlevel(filter_ID)
VALUES (1), (0), (1), (0), (0), (1),(1),(1),(1);
The "% s" is invalid syntax. If that's a literal, then it needs to be enclosed in quotes:
WHERE filter_id = '% s'
(But that fix doesn't appear to be right. It almost looks as if the MySQL statement is being generated with a sprintf, and there was intended to be a '%s' placeholder that was supposed to be replaced with an value.)
Also, there's a closing parenthesis and alias missing from the end of the statement:
) foo
And this:
WHERE cvm_alumni.profile_status = 1
should be changed to this:
WHERE alum.profile_status = 1
(The table is assigned an alias, the column reference should be qualified with the alias, not the table_name)
It's also a good idea to qualify the references all column references, including educationlevel_id, highest_edu and name. (That's not necessarily a problem with the statement, unless MySQL is throwing an "ambiguous column" error, but I prefer to insulate my statements from any "ambiguous column" error that will crop up when new columns are added.)
SELECT SQL_CALC_FOUND_ROWS id
FROM (SELECT taba.id
FROM (
SELECT alum.id
FROM cvm_education edu
JOIN cvm_alumni alum
ON alum.id = edu.alumni_id
WHERE alum.profile_status = 1
AND `highest_edu` IN
(
SELECT `name`
FROM cvm_filter_educationlevels
JOIN cvm_educationlevel edulevels
ON `educationlevel_id` = edulevels.id
WHERE `filter_id` = '% s'
)
) taba
) foo