How to reference / insert the IDs inserted in the last two insert statements within the same Oracle stored procedure? - sql

I have a stored procedure that is inserting values based off a cursor that I wrote. I am trying to put in a calculated value summed by day. However, (I looked online and couldn't find any examples that do this); how do I reference a previously generated ID (both for Value and Calculation) that are both generated by a trigger?
I was thinking of possibly using a select from the table with the query pulling the most recent id from both tables? I was thinking that that may be too easy to be correct though.
This is my code:
create or replace PROCEDURE TEST_PROC IS
Cursor c1 is
SELECT SUM(v.value_tx) AS sum_of_values ,
e.entity_id AS entity_id ,
e.entity_name_tx AS entity_name ,
e.ei_id_tx AS ei_id ,
v.create_dt AS create_dt ,
v.hr_num AS hr_num ,
v.utc_offset ,
v.data_date ,
v.hr_utc ,
v.hr ,
ff.form_field_id,
s.survey_respondent_id,
v.data_code ,
'N' AS processed
FROM value v
join submission_value sv
ON v.value_id = sv.value_id
join form_field ff
ON sv.form_field_id = ff.form_field_id
join submission s
ON sv.submission_id = s.submission_id
join survey_respondent sr
ON s.survey_respondent_id = s.survey_respondent_id
join entity e
ON sr.entity_id = e.entity_id
WHERE ei_id_tx IN ('ABC', 'ZYX', 'ADA', 'AZL', 'BAN', 'CAB')
AND ff.form_field_id IN ('55', '77')
GROUP BY e.entity_id,
e.entity_name_tx,
e.ei_id_tx,
v.create_dt,
v.hr_num,
v.utc_offset,
v.data_date,
v.hr_utc,
v.hr,
v.data_code;
l_var c1%ROWTYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1 into l_var;
EXIT WHEN c1%NOTFOUND;
insert into value (product_id, data_source_id, unit_cd, value_tx, utc_offset, data_date, hr_utc, hr, hr_num, data_code, create_dt, create_user_id, modify_dt, modify_user_id, effective_dt, inactive_dt)
Values ('77', '555', 'NA', l_var.sum_of_values, l_var.utc_offset, l_var.data_date, l_var.hr_utc, l_var.hr, l_var.hr_num, l_var.data_code, sysdate, '1', null, null, null, null);
insert into calculation (survey_respondent_id, calculation_dt, calculation_name_tx, create_dt, create_user_id, modify_dt, modify_user_id, effective_dt, inactive_dt, publication_issue_id, entity_survey_id)
Values (l_var.survey_respondent_id, sysdate, sysdate, sysdate, '1', null, null, null, null, null, null);
insert into calculation_value (calculation_id, value_id, form_field_id, create_dt, create_user_id, modify_dt, modify_user_id, effective_Dt, inactive_dt)
Values ( ??, ??, l_var.form_field_id, sysdate, '1', null, null, null, null);
END LOOP;
CLOSE c1;
END TEST_PROC;
*Calculation Table*
Calculation_ID Survey_Respondent_ID Calculation_Dt Calculation_Name
Create_Dt Create_User_id
*Value Table*
Value_Id Value Data_Date HR Data_Code Create_Dt ..

Don't know if I understand completly, but maybe this is what you are looking for? I may have typed it wrong.
create or replace PROCEDURE TEST_PROC IS
Cursor c1 is
SELECT SUM(v.value_tx) AS sum_of_values ,
e.entity_id AS entity_id ,
e.entity_name_tx AS entity_name ,
e.ei_id_tx AS ei_id ,
v.create_dt AS create_dt ,
v.hr_num AS hr_num ,
v.utc_offset ,
v.data_date ,
v.hr_utc ,
v.hr ,
ff.form_field_id,
s.survey_respondent_id,
v.data_code ,
'N' AS processed
FROM value v
join submission_value sv
ON v.value_id = sv.value_id
join form_field ff
ON sv.form_field_id = ff.form_field_id
join submission s
ON sv.submission_id = s.submission_id
join survey_respondent sr
ON s.survey_respondent_id = s.survey_respondent_id
join entity e
ON sr.entity_id = e.entity_id
WHERE ei_id_tx IN ('ABC', 'ZYX', 'ADA', 'AZL', 'BAN', 'CAB')
AND ff.form_field_id IN ('55', '77')
GROUP BY e.entity_id,
e.entity_name_tx,
e.ei_id_tx,
v.create_dt,
v.hr_num,
v.utc_offset,
v.data_date,
v.hr_utc,
v.hr,
v.data_code;
l_var c1%ROWTYPE;
v_value_id value.value_id%type;
v_calculation_id calculation.calculation_id%type;
BEGIN
OPEN c1;
LOOP
FETCH c1 into l_var;
EXIT WHEN c1%NOTFOUND;
insert into value (value_id,product_id, data_source_id, unit_cd, value_tx, utc_offset, data_date, hr_utc, hr, hr_num, data_code, create_dt, create_user_id, modify_dt, modify_user_id, effective_dt, inactive_dt)
Values (null,'77', '555', 'NA', l_var.sum_of_values, l_var.utc_offset, l_var.data_date, l_var.hr_utc, l_var.hr, l_var.hr_num, l_var.data_code, sysdate, '1', null, null, null, null)
returning value_id into v_value_id;
insert into calculation (calculation_id,survey_respondent_id, calculation_dt, calculation_name_tx, create_dt, create_user_id, modify_dt, modify_user_id, effective_dt, inactive_dt, publication_issue_id, entity_survey_id)
Values (null,l_var.survey_respondent_id, sysdate, sysdate, sysdate, '1', null, null, null, null, null, null)
returning calculation_id into v_calculation_id;
insert into calculation_value (calculation_id, value_id, form_field_id, create_dt, create_user_id, modify_dt, modify_user_id, effective_Dt, inactive_dt)
Values ( v_calculation_id, v_value_id, l_var.form_field_id, sysdate, '1', null, null, null, null);
END LOOP;
CLOSE c1;
END TEST_PROC;

Related

How to have pl/sql code skip over NULL values in multiple columns

I am currently writing a PL/SQL script that is taking data from a cursor. The cursor is grouping by multiple grouping sets so I am returning null values for multiple columns in a select few entries. Is there a way I can have my pl/sql script skip over these entries during my insert statement? I've tried using an IF statement but that doesn't work. Below is my code: Thanks in advance!
create or replace Procedure TEST_PROC IS
CURSOR c1 is
select sum(v.value_tx) as sum_of_values
, max(c.create_dt) as max_calculation_dt
, max(TRUNC(to_date((v.hr + ((v.utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss'), 'iw')) as REPORT_PERIOD_DT
, to_char((v.hr + ((v.utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss') as CONVERTED_HR
, v.utc_offset
, ff.form_field_label_tx
, v.region_id
, v.hr_num
, v.data_code
from value v
join calculation_value cv on v.value_id = cv.value_id
join calculation c on cv.calculation_id = c.calculation_id
join form_field ff on cv.form_field_id = ff.form_field_id
where v.hr is not null
and v.data_code is not null
and v.utc_offset is not null
group by grouping sets(
(v.region_id, v.data_code, v.hr_num, v.utc_offset, ff.form_field_label_tx, ff.form_field_id, to_char(TRUNC(to_date((v.hr + ((v.utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss'), 'iw'), 'dddyyyy'), TRUNC(to_date((v.hr + ((v.utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss'), 'iw'), to_char((hr + ((utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss'), ),
(v.region_id, v.data_code, v.hr_num, v.utc_offset, ff.form_field_label_tx, ff.form_field_id, to_char(TRUNC(to_date((v.hr + ((v.utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss'), 'iw'), 'dddyyyy'), TRUNC(to_date((v.hr + ((v.utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss'), 'iw'), v.utc_offset), v.data_code
)
order by max(TRUNC(to_date((v.hr + ((v.utc_offset - 1)/24)), 'DD-MM-YY hh24:mi:ss'), 'iw')) desc;
l_var c1%ROWTYPE;
v_value_id value.value_id%type;
v_calculation_id calculation.calculation_id%type;
--
BEGIN
Open c1;
FETCH c1 into l_var;
insert into calculation (calculation_id, calculation_date, calculation_name, report_period_dt)
VALUES (null, sysdate, 'AGGWKL ' || l_var.REPORT_PERIOD_DT, l_var.report_period_dt)
returning calculation_id into v_calculation_id;
Close c1;
Open c1;
LOOP
FETCH c1 into l_var;
EXIT when c1%NOTFOUND;
IF l_var.utc_offset is not null
THEN
insert into value (value_id, energy_product_id, data_source_id, unit_cd, value_tx, utc_offset, data_date, hr_utc, hr, hr_num, data_code)
VALUES (null, '777', '5', 'NA', l_var.sum_of_values, l_var.utc_offset, l_var.data_date, null, null, l_var.hr_num, l_var.data_code)
returning value_id into v_value_id;
insert into calculation_value(calculation_value_id, calculation_id, value_id, form_field_id
values (null, v_calculation_id, v_value_id, l_var.form_field_id);
END LOOP;
CLOSE c1;
END TEST_PROC;
You didn't point out in which table You get nulls so I'll try to answer only thing I see. It's a bit hard to write exact answer without some test data but as far I can see You have couple of problems:
insert into calculation (calculation_id, calculation_date, calculation_name, report_period_dt)
VALUES (null, sysdate, 'AGGWKL ' || l_var.REPORT_PERIOD_DT, _var.report_period_dt) returning calculation_id into v_calculation_id;
here You are inserting null into calculation table and then returning it into v_calculation_id
Similar thing is happening here:
insert into value (value_id, energy_product_id, data_source_id, unit_cd,
value_tx, utc_offset, data_date, hr_utc, hr, hr_num, data_code)
VALUES (null, '777', '5', 'NA', l_var.sum_of_values, l_var.utc_offset,
l_var.data_date, null, null, l_var.hr_num, l_var.data_code) returning value_id into v_value_id;
You are inserting null into value table and then returning it into v_value_id
and in the end You are inserting all those nulls into calculation_value here:
insert into calculation_value(calculation_value_id, calculation_id, value_id, form_field_id
values (null, v_calculation_id (this is null), v_value_id (this is null), l_var.form_field_id);

If query returns one or more rows, return the row/rows and exit

I have three statements. If any of them returns anything I want that to be returned and the query to exit.
select *
from connexion
where origin = 'Stockholm'
and destination = 'Berlin';
-- IF IT RETURNS ONE OR MORE ROWS THEN RETURN ROW/ROWS AND EXIT, ELSE GO TO STATEMENT BELOW
select *
from connexion c1, connexion c2
where c1.origin = 'Stockholm'
and c2.destination = 'Berlin'
and c1.destination = c2.origin;
-- IF IT RETURNS ONE OR MORE ROWS THEN RETURN ROW/ROWS AND EXIT, ELSE GO TO STATEMENT BELOW
select *
from connexion c1, connexion c2, connexion c3
where c1.origin = 'Stockholm'
and c3.destination = 'Berlin'
and c1.destination = c2.origin
and c2.destination = c3.origin;
-- IF IT RETURNS ONE OR MORE ROWS THEN RETURN ROW/ROWS AND EXIT, ELSE EXIT
Here's the query to create the database. I want to retrieve a result where I can go from Stockholm to Berlin via any of the available connexions.
create table busstop(
city varchar(50),
country varchar(50) not null,
streetAddress varchar(50) not null,
primary key (city)
);
create table driver(
driverPnr varchar(13),
name varchar(50) not null,
address varchar(50) not null,
phone varchar(12) not null,
primary key (driverPnr)
);
create table customer(
customerPnr varchar(13),
name varchar(50) not null,
email varchar(50) not null,
phone varchar(12) not null,
primary key (customerPnr)
);
create table connexion(
connexionId serial not null,
origin varchar(50) not null,
destination varchar(50) not null,
primary key (connexionId),
foreign key (origin) references busstop(city),
foreign key (destination) references busstop(city)
);
create table trip(
tripId serial not null,
connexionId integer not null,
departure timestamp not null,
arrival timestamp not null,
driverPnr varchar(13),
priceAmount integer not null,
seats integer not null,
primary key (tripId),
foreign key (connexionId) references connexion(connexionId),
foreign key (driverPnr) references driver(driverPnr)
);
create table booking(
customerPnr varchar(13) not null,
tripId integer not null,
seats integer not null,
primary key (customerPnr, tripId),
foreign key (customerPnr) references customer(customerPnr),
foreign key (tripId) references trip(tripId)
);
insert into busstop(city, country, streetAddress) values
('Stockholm', 'Sweden', 'Byvägen 1'),
('Copenhagen', 'Denmark', 'Vesterbrogade 23'),
('Berlin', 'Germany', 'Europaplatz 4'),
('Amsterdam', 'Netherlands', 'Stationsplein 17'),
('Prague', 'Czech Republic', 'Wilsonova 10');
insert into connexion(origin, destination) values
('Stockholm', 'Copenhagen'),
('Copenhagen', 'Stockholm'),
('Copenhagen', 'Berlin'),
('Berlin', 'Copenhagen'),
('Copenhagen', 'Amsterdam'),
('Amsterdam', 'Copenhagen'),
('Berlin', 'Prague'),
('Prague', 'Berlin'),
('Amsterdam', 'Berlin'),
('Berlin', 'Amsterdam'),
('Amsterdam', 'Prague'),
('Prague', 'Amsterdam');
insert into trip(connexionId, departure, arrival, priceAmount, seats) values
-- Exits on 2018-04-21
-- Stockholm - Copenhagen / Copenhagen - Stockholm, 3 hours
(1, '2018-04-22 07:00:00', '2018-04-22 10:00:00', 200, 35),
(2, '2018-04-22 18:00:00', '2018-04-22 21:00:00', 200, 35),
-- Copenhagen - Berlin / Berlin - Copenhagen, 7 hours
(3, '2018-04-22 10:00:00', '2018-04-22 17:00:00', 500, 35),
(4, '2018-04-22 11:00:00', '2018-04-22 18:00:00', 500, 35),
-- Copenhagen - Amsterdam / Amsterdam - Copenhagen, 9 hours
(5, '2018-04-22 10:00:00', '2018-04-22 19:00:00', 800, 35),
(6, '2018-04-22 09:00:00', '2018-04-22 18:00:00', 800, 35),
-- Berlin - Prague / Prague - Berlin, 4 hours
(7, '2018-04-22 17:00:00', '2018-04-22 21:00:00', 300, 35),
(8, '2018-04-22 07:00:00', '2018-04-22 11:00:00', 300, 35),
-- Amsterdam - Berlin / Berlin - Amsterdam, 7 hours
(9, '2018-04-22 07:00:00', '2018-04-22 14:00:00', 500, 35),
(10, '2018-04-22 14:00:00', '2018-04-22 21:00:00', 500, 35),
-- Amsterdam - Prague / Prague - Amsterdam, 9 hours
(11, '2018-04-22 05:00:00', '2018-04-22 14:00:00', 800, 35),
(12, '2018-04-22 14:00:00', '2018-04-22 23:00:00', 800, 35);
If I go from Stockholm to Berlin the query has to first check if there are any direct connexions between Stockholm and Berlin. If no, then it has to check if there are any connexion with ONE stopover, if so retrieve a row for that. If there's none, proceed with checking if there's any connexion with TWO stopovers, and it continues until it has checked THREE stopovers. (no one would want to travel from Stockholm to Berlin with more than three stopovers..).. It's so hard to explain what I want to achieve but I hope you get the point :)
You can do this with multiple joins:
select c1.*, c2.*, c3.*
from connexion c1 left join
connexion c2
on c1.origin = 'Stockholm' and
(c1.destination = 'Berlin' or
(c1.destination <> 'Berlin' and c2.destination = 'Berlin')
) left join
connection c3
on c2.destination = c3.destination and
(c2.destination <> 'Berlin' and
c1.destination <> 'Berlin'
);
a reach and this is tsql
this is just direct or 1 stop
select 'Stockholm' as origin_, 'Berlin' as destination_, *
from connexion c1
join connexion c2
on c1.origin = 'Stockholm'
and ( c1.destination = 'Berlin'
or (c1.destination <> 'Berlin' and c2.destination = 'Berlin')
)
This is sql server but according to the docs postgresql supports recursion.
Stop is just the last stop. This does not show you all stops. Cnt is the number of stops.
declare #t table (orig varchar(20), dest varchar(20)
, primary key (orig, dest));
insert into #t values
('Stockholm', 'Copenhagen'),
('Copenhagen', 'Stockholm'),
('Copenhagen', 'Berlin'),
('Berlin', 'Copenhagen'),
('Copenhagen', 'Amsterdam'),
('Amsterdam', 'Copenhagen'),
('Berlin', 'Prague'),
('Prague', 'Berlin'),
('Amsterdam', 'Berlin'),
('Berlin', 'Amsterdam'),
('Amsterdam', 'Prague'),
('Prague', 'Amsterdam');
with cte as
( select t.orig, t.orig as 'stop', t.dest, 1 as cnt
from #t t
union all
select cte.orig, t.orig, t.dest, cnt + 1
from #t t
join cte
on cte.dest = t.orig
and t.dest <> cte.orig --don't loop back home
and cnt < 4
)
select *
from cte
where orig = 'Stockholm'
and dest = 'Berlin'
order by cnt, cte.stop
This will not prevent looping in route. By limiting cnt the loops are eliminated. It prevents going back to the original city.
You can use GOTo Statement in SQL . In below code you can assign your query counts and then in if condition you can count if its grater than 0 then GOTO respective query.
DECLARE #a Int
DECLARE #b Int
SELECT #a = 10
SELECT #b = 5
BEGIN
IF #a>#0 GOTO Greater
IF #b>0 GOTO Lesser
END
Greater: SELECT #a
Lesser: SELECT #b

Find the latest payment value in between "valid" period

It's quite hard for me to write nice title, so I'll try to describe the problem here in detail.
We have table [dbo].[LEASE_APPLICATIONS_AUDIT_LOG] that stores the historical data with changed datetimes. In case if the status of the data was NOT IN ('E', 'F', 'I', 'O', 'X') then that means that it was approved at that moment and if the status is other than these ones, then it is not approved. It can become approved and not approved in any order and many times. For example:
'2010.01.01', 'A'
'2010.02.01', 'B'
'2010.03.01', 'E'
'2010.04.01', 'Z'
That means that the record was approved from 2010.01.01 till 2010.03.01 and then was approved again at 2010.04.01.
There is another table [dbo].[LEASE_FINANCING_AUDIT_LOG] that stores the base payment amount that was at that time. For example if for the same record I would have such entries:
'2010.01.01', 123
'2010.04.01', 321
then that means that from base payment was 123 from 2010.01.01 till 2010.03.01 (became unapproved) and then from 2010.04.01 the value became to be 321.
There could be various combination of status changes and there could be different base payment values at any period of times.
So, the goal is to find the LATEST base_payment value that was in between APPROVED period.
Here are the scripts we've made so far. There are 2 tables with that data and the function. Other code snippets are taken from unit tests that's why they are like that and they will output 'bad' string if the logic is not as expected one. The function is working, but I do not really like the TOP 1/ORDER BY approach and trying to find if there is better way to achieve that. Any thoughts?
SET NOCOUNT ON;
CREATE TABLE [dbo].[LEASE_APPLICATIONS_AUDIT_LOG]
(
[LEASE_APPLICATION] CHAR(8)
, [APPLICATION_STATUS_CODE] CHAR(1)
, [CHANGED_DATE] DATETIME2(7) NOT NULL
);
GO
CREATE TABLE [dbo].[LEASE_FINANCING_AUDIT_LOG]
(
[LEASE_APPLICATION] CHAR(8)
, [BASE_PAYMENT] DECIMAL(10, 2) NULL
, [CHANGED_DATE] DATETIME2(7) NOT NULL
);
GO
CREATE FUNCTION [dbo].[post_approval_payment_amount] (#lease_application CHAR(8))
RETURNS TABLE
AS
RETURN (
SELECT TOP 1 lfal.BASE_PAYMENT AS post_approval_payment_amount
FROM LEASE_APPLICATIONS_AUDIT_LOG laal
CROSS APPLY
(
SELECT TOP 1 lf.BASE_PAYMENT
FROM LEASE_FINANCING_AUDIT_LOG lf
WHERE lf.LEASE_APPLICATION = laal.LEASE_APPLICATION
AND lf.CHANGED_DATE < COALESCE((
SELECT TOP 1 la.CHANGED_DATE
FROM LEASE_APPLICATIONS_AUDIT_LOG la
WHERE la.LEASE_APPLICATION = laal.LEASE_APPLICATION
AND la.CHANGED_DATE > laal.CHANGED_DATE
ORDER BY la.CHANGED_DATE
), CAST('9999-12-31 23:59:59' AS DATETIME))
ORDER BY lf.CHANGED_DATE DESC
) lfal
WHERE laal.LEASE_APPLICATION = #lease_application
AND laal.APPLICATION_STATUS_CODE NOT IN ('E', 'F', 'I', 'O', 'X')
ORDER BY laal.CHANGED_DATE DESC
);
GO
DECLARE #lease_application CHAR(8) = '35163328'
, #base_payment DECIMAL = 209.12
, #expected DECIMAL = 209.12
, #actual DECIMAL;
DECLARE #la AS TABLE
(
change_date DATETIME2(7)
, application_status_code CHAR(1) NULL
, base_amount DECIMAL NULL
, is_laal BIT
);
INSERT INTO #la ( change_date
, application_status_code
, base_amount
, is_laal
)
VALUES ('2017-05-11 03:46:26.4800000', 'K', NULL, 1)
, ('2017-05-11 03:48:05.0600000', NULL, #base_payment, 0)
, ('2017-06-21 14:07:51.2200000', 'X', NULL, 1);
INSERT INTO dbo.lease_applications_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, APPLICATION_STATUS_CODE
)
SELECT #lease_application
, l.change_date
, l.application_status_code
FROM #la AS l
WHERE l.is_laal = 1;
INSERT INTO dbo.lease_financing_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, BASE_PAYMENT
)
SELECT #lease_application
, l.change_date
, l.base_amount
FROM #la AS l
WHERE l.is_laal = 0;
SELECT #actual = post_approval_payment_amount
FROM [dbo].[post_approval_payment_amount](#lease_application);
IF (#expected <> #actual) SELECT 'Test 1 failed'
ELSE SELECT 'Test 1 passed';
SELECT #lease_application = '30000152'
, #base_payment = 622.15
, #expected = 622.15;
DELETE FROM #la;
INSERT INTO #la ( change_date
, application_status_code
, base_amount
, is_laal
)
VALUES ('2017-05-11 03:46:26.4800000', 'z', NULL, 1)
, ('2017-05-11 03:48:05.0600000', NULL, #base_payment, 0);
INSERT INTO dbo.lease_applications_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, APPLICATION_STATUS_CODE
)
SELECT #lease_application
, l.change_date
, l.application_status_code
FROM #la AS l
WHERE l.is_laal = 1;
INSERT INTO dbo.lease_financing_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, BASE_PAYMENT
)
SELECT #lease_application
, l.change_date
, l.base_amount
FROM #la AS l
WHERE l.is_laal = 0;
SELECT #actual = post_approval_payment_amount
FROM [dbo].[post_approval_payment_amount](#lease_application);
IF (#expected <> #actual) SELECT 'Test 2 failed'
ELSE SELECT 'Test 2 passed';
SELECT #lease_application = '38768578'
, #base_payment = 453.70
, #expected = NULL
, #actual = NULL;
DELETE FROM #la;
INSERT INTO #la ( change_date
, application_status_code
, base_amount
, is_laal
)
VALUES ('2017-05-11 03:46:26.4800000', 'L', NULL, 1)
, ('2017-06-09 12:00:36.2000000', 'X', NULL, 1)
, ('2017-06-12 03:48:05.0600000', NULL, #base_payment, 0);
INSERT INTO dbo.lease_applications_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, APPLICATION_STATUS_CODE
)
SELECT #lease_application
, l.change_date
, l.application_status_code
FROM #la AS l
WHERE l.is_laal = 1;
INSERT INTO dbo.lease_financing_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, BASE_PAYMENT
)
SELECT #lease_application
, l.change_date
, l.base_amount
FROM #la AS l
WHERE l.is_laal = 0;
SELECT #actual = post_approval_payment_amount
FROM [dbo].[post_approval_payment_amount](#lease_application);
IF (#actual IS NOT NULL) SELECT 'Test 3 failed'
ELSE SELECT 'Test 3 passed';
SELECT #lease_application = '38282661'
, #base_payment = 451.25
, #expected = 451.25;
DELETE FROM #la;
INSERT INTO #la ( change_date
, application_status_code
, base_amount
, is_laal
)
VALUES ('2017-05-11 03:46:26.4800000', 'O', NULL, 1)
, ('2017-05-11 03:48:05.0600000', NULL, #base_payment, 0)
, ('2017-07-05 10:52:14.6800000', 'O', NULL, 1)
, ('2017-07-05 11:10:24.0400000', 'E', NULL, 1)
, ('2017-07-05 11:10:25.6000000', 'E', NULL, 1)
, ('2017-07-05 11:10:49.1900000', 'L', NULL, 1)
, ('2017-07-06 00:04:30.6400000', 'O', NULL, 1);
INSERT INTO dbo.lease_applications_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, APPLICATION_STATUS_CODE
)
SELECT #lease_application
, l.change_date
, l.application_status_code
FROM #la AS l
WHERE l.is_laal = 1;
INSERT INTO dbo.lease_financing_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, BASE_PAYMENT
)
SELECT #lease_application
, l.change_date
, l.base_amount
FROM #la AS l
WHERE l.is_laal = 0;
SELECT #actual = post_approval_payment_amount
FROM [dbo].[post_approval_payment_amount](#lease_application);
IF (#expected <> #actual) SELECT 'Test 4 failed'
ELSE SELECT 'Test 4 passed';
SELECT #lease_application = '38768578'
, #base_payment = 453.70
, #expected = 453.70;
DELETE FROM #la;
INSERT INTO #la ( change_date
, application_status_code
, base_amount
, is_laal
)
VALUES ('2017-05-11 03:46:26.4800000', 'L', NULL, 1)
, ('2017-05-11 03:48:05.0600000', NULL, 200, 0)
, ('2017-05-12 03:48:05.0600000', NULL, #base_payment, 0)
, ('2017-06-09 12:00:36.2000000', 'X', NULL, 1)
, ('2017-09-18 11:57:13.5100000', NULL, 100, 0);
INSERT INTO dbo.lease_applications_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, APPLICATION_STATUS_CODE
)
SELECT #lease_application
, l.change_date
, l.application_status_code
FROM #la AS l
WHERE l.is_laal = 1;
INSERT INTO dbo.lease_financing_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, BASE_PAYMENT
)
SELECT #lease_application
, l.change_date
, l.base_amount
FROM #la AS l
WHERE l.is_laal = 0;
SELECT #actual = post_approval_payment_amount
FROM [dbo].[post_approval_payment_amount](#lease_application);
IF (#expected <> #actual) SELECT 'Test 5 failed'
ELSE SELECT 'Test 5 passed';
SELECT #lease_application = '38768578'
, #base_payment = 453.70
, #expected = 453.70;
DELETE FROM #la;
INSERT INTO #la ( change_date
, application_status_code
, base_amount
, is_laal
)
VALUES ('2017-05-11 03:46:26.4800000', 'L', NULL, 1)
, ('2017-05-11 03:48:05.0600000', NULL, #base_payment, 0)
, ('2017-06-09 12:00:36.2000000', 'X', NULL, 1)
, ('2017-09-18 11:57:13.5100000', NULL, 100, 0);
INSERT INTO dbo.lease_applications_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, APPLICATION_STATUS_CODE
)
SELECT #lease_application
, l.change_date
, l.application_status_code
FROM #la AS l
WHERE l.is_laal = 1;
INSERT INTO dbo.lease_financing_audit_log ( LEASE_APPLICATION
, CHANGED_DATE
, BASE_PAYMENT
)
SELECT #lease_application
, l.change_date
, l.base_amount
FROM #la AS l
WHERE l.is_laal = 0;
SELECT #actual = post_approval_payment_amount
FROM [dbo].[post_approval_payment_amount](#lease_application);
IF (#expected <> #actual) SELECT 'Test 6 failed'
ELSE SELECT 'Test 6 passed';
DROP TABLE [dbo].[LEASE_APPLICATIONS_AUDIT_LOG];
GO
DROP TABLE [dbo].[LEASE_FINANCING_AUDIT_LOG];
GO
DROP FUNCTION [dbo].[post_approval_payment_amount];
GO
You asked for some thoughts about alternative approaches. You could use these ideas individually or in combination:
Remember that JOINs may be done using an operator other than the equal sign, so you could for example join your tables ON LEASE_APPLICATIONS_AUDIT_LOG.CHANGED_DATE <= LEASE_FINANCING_AUDIT_LOG.CHANGED_DATE.
The LAG and LEAD functions are highly optimal functions for retrieving "nearby" records. The third parameter even allows you to specify the value that will be returned in the event a record is not found - a convenient place to insert your CAST('9999-12-31 23:59:59' AS DATETIME default.
Never underestimate the clarity and performance that can be achieved by the proper use of Common Table Expressions (using the WITH clause).

SQL Server query help needed for joining

I have these three tables in SQL Server 2012.
CREATE TABLE [dbo].[ClientInfo]
(
[ClientID] [int] IDENTITY(1,1) NOT NULL,
[ClientName] [varchar](50) NULL,
[ClientAddress] [varchar](50) NULL,
[City] [varchar](50) NULL,
[State] [varchar](50) NULL,
[DOB] [date] NULL,
[Country] [varchar](50) NULL,
[Status] [bit] NULL,
PRIMARY KEY (ClientID)
)
CREATE TABLE [dbo].[ClientInsuranceInfo]
(
[InsID] [int] IDENTITY(1,1) NOT NULL,
[ClientID] [int] NULL,
[InsTypeID] [int] NULL,
[ActiveDate] [date] NULL,
[InsStatus] [bit] NULL,
PRIMARY KEY (InsID)
)
CREATE TABLE [dbo].[TypeInfo]
(
[TypeID] [int] IDENTITY(1,1) NOT NULL,
[TypeName] [varchar](50) NULL,
PRIMARY KEY (TypeID)
)
Some sample data to execute the query
insert into ClientInfo (ClientName, State, Country, Status)
values ('Lionel Van Praag', 'NSW', 'Australia', 'True')
insert into ClientInfo (ClientName, State, Country, Status)
values ('Bluey Wilkinson', 'NSW', 'Australia', 'True')
insert into ClientInfo (ClientName, State, Country, Status)
values ('Jack Young', 'NSW', 'Australia', 'True')
insert into ClientInfo (ClientName, State, Country, Status)
values ('Keith Campbell', 'NSW', 'Australia', 'True')
insert into ClientInfo (ClientName, State, Country, Status)
values ('Tom Phillis', 'NSW', 'Australia', 'True')
insert into ClientInfo (ClientName, State, Country, Status)
values ('Barry Smith', 'NSW', 'Australia', 'True')
insert into ClientInfo (ClientName, State, Country, Status)
values ('Steve Baker', 'NSW', 'Australia', 'True')
insert into TypeInfo (TypeName) values ('CarInsurance')
insert into TypeInfo (TypeName) values ('MotorcycleInsurance')
insert into TypeInfo (TypeName) values ('HeavyVehicleInsurance')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('1', '1', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('1', '2', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('2', '1', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('2', '2', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('2', '3', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('3', '1', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('4', '1', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('4', '3', '2000-01-11', 'True')
insert into ClientInsuranceInfo (ClientID, InsTypeID, ActiveDate, InsStatus)
values ('5', '2', '2000-01-11', 'True')
I have written the following query which returns only those clients who have 'MotorcycleInsurance' type:
select distinct
ClientInfo.ClientID, ClientInfo.ClientName, TypeInfo.TypeName
from
ClientInfo
left join
ClientInsuranceInfo on ClientInfo.ClientID = ClientInsuranceInfo.ClientID
left join
TypeInfo on ClientInsuranceInfo.InsTypeID = TypeInfo.TypeID
and TypeInfo.TypeID = 2
where
typeinfo.TypeName is not null
But I want to do the following things
I want to return all clients who have 'MotorcycleInsurance' along with rest of clients who do not have 'MotorcycleInsurance' as well.
TypeName will be returned as NULL who do not have 'MotorcycleInsurance'
ClientID have to be unique in the result set.
Do not want to use UNION / UNION ALL.
How can I do this?
My required answer will be as follow
Try this one using ROW_NUMBER:
select a.ClientID, a.ClientName, a.TypeName
from
(
select distinct ClientInfo.ClientID, ClientInfo.ClientName, TypeInfo.TypeName, ROW_NUMBER() over(partition by ClientInfo.ClientID order by case when TypeName is null then 1 else 0 end) as rn
from ClientInfo
left join ClientInsuranceInfo on ClientInfo.ClientID = ClientInsuranceInfo.ClientID
left join TypeInfo on ClientInsuranceInfo.InsTypeID = TypeInfo.TypeID and TypeInfo.TypeID = 2
) a
where rn = 1
Edit: Updated ordering by case statement in Row_Number :)
Just remove your where clause and change join condition slightly
select distinct ClientInfo.ClientID, ClientInfo.ClientName, TypeInfo.TypeName
from ClientInfo
left join ClientInsuranceInfo
on ClientInfo.ClientID = ClientInsuranceInfo.ClientID
and ClientInsuranceInfo.InsTypeID = 2
left join TypeInfo on ClientInsuranceInfo.InsTypeID = TypeInfo.TypeID
SELECT CI.ClientID, CI.ClientName, TI.TypeName
FROM dbo.ClientInfo AS CI
LEFT JOIN (SELECT ClientID, InsTypeID
FROM dbo.ClientInsuranceInfo
WHERE InsTypeID = 2
GROUP BY ClientID, InsTypeID ) AS CII ON CI.ClientID = CII.ClientID
LEFT JOIN dbo.TypeInfo AS TI ON CII.InsTypeID = TI.TypeID;

how to select the min value using having key word

I have created the table stu_dep_det
CREATE TABLE `stu_dept_cs` (
`s_d_id` int(10) unsigned NOT NULL auto_increment,
`stu_name` varchar(15) , `gender` varchar(15) , `address` varchar(15),`reg_no` int(10) ,
`ex_no` varchar(10) ,
`mark1` varchar(10) ,
`mark2` varchar(15) ,
`mark3` varchar(15) ,
`total` varchar(15) ,
`avg` double(2,0),
PRIMARY KEY (`s_d_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC AUTO_INCREMENT=8 ;
then Inserted the values
INSERT INTO `stu_dept_cs` (`s_d_id`, `stu_name`, `gender`, `address`, `reg_no`, `ex_no`, `mark1`, `mark2`, `mark3`, `total`, `avg`) VALUES
(1, 'alex', 'm', 'chennai', 5001, 's1', '70', '90', '95', '255', 85),
(2, 'peter', 'm', 'chennai', 5002, 's1', '80', '70', '90', '240', 80),
(6, 'parv', 'f', 'mumbai', 5003, 's1', '88', '60', '80', '228', 76),
(7, 'basu', 'm', 'kolkatta', 5004, 's1', '85', '95', '56', '236', 79);
I want to select the min(avg) using having keyword and I have used the following sql statement
SELECT * FROM stu_dept_cs s having min(avg)
Is it correct or not plz write the correct ans....
select somecolumn1,somecolumn2
from stu_dept_cs
group by somecolumn1,somecolumn2,avg
having avg = min(avg)
or
with t1
(select rownumber() over (partition by somecolumn1,somecolumn2
order by somecolumn1,somecolumn2,avg asc) as rownum
from stu_dept_cs )
select * from t1 where rownum=1
SELECT t1.* FROM stu_dept_cs t1
LEFT JOIN stu_dept_cs t2
ON t1.avg > t2.avg
WHERE t2.stu_name IS NULL;