LINQ Left Join on Max Date - linq

Ok so here are my tables in the database:
CREATE DATABASE Temp
GO --------------------------
USE Temp
GO --------------------------
CREATE TABLE Table1
(
Table1Id INT IDENTITY(1, 1) ,
Name VARCHAR(20) ,
CONSTRAINT pk_Table1 PRIMARY KEY ( Table1Id )
)
GO --------------------------
CREATE TABLE Table2
(
Table2Id INT IDENTITY(1, 1) ,
Table1Id INT ,
NAME VARCHAR(20) ,
TheDate SMALLDATETIME ,
CONSTRAINT pk_Table2 PRIMARY KEY ( Table2Id ) ,
CONSTRAINT fk_Table2_Table1 FOREIGN KEY ( Table1Id ) REFERENCES Table1 ( Table1Id )
)
GO --------------------------
INSERT INTO Table1
( Name )
VALUES ( 'Stack Overflow' )
GO --------------------------
INSERT INTO Table1
( Name )
VALUES ( 'Expert Sex Change' )
GO --------------------------
INSERT INTO Table1
( Name )
VALUES ( 'Code Project' )
GO --------------------------
INSERT INTO dbo.Table2
( Table1Id ,
NAME ,
TheDate
)
VALUES ( 1 ,
'S1' ,
'11-01-2012'
)
GO --------------------------
INSERT INTO dbo.Table2
( Table1Id ,
NAME ,
TheDate
)
VALUES ( 1 ,
'S2' ,
'11-01-2013'
)
GO --------------------------
INSERT INTO dbo.Table2
( Table1Id ,
NAME ,
TheDate
)
VALUES ( 2 ,
'E1' ,
'10-01-2013'
)
And here's my LINQ:
from t1 in Table1s
join t2 in Table2s.OrderByDescending(x => x.TheDate)
on t1.Table1Id equals t2.Table1Id into tt
from t2 in tt.DefaultIfEmpty()
select new
{
t1.Table1Id,
t1.Name,
t2.NAME,
t2.TheDate
}
This one returns:
Table1Id - Name - NAME - TheDate
1 - Stack Overflow - S2 - 11/1/2013
2 - Expert Sex Change - E1 - 10/1/2013
1 - Stack Overflow - S1 - 11/1/2012
3 - Code Project - null - null
I want the LINQ query not to return the third line, as is from an older Date Value.

I think I got it, the answer is:
from t1 in Table1s
join t2 in Table2s
on t1.Table1Id equals t2.Table1Id
into tt
from x in tt.DefaultIfEmpty()
// where ... t1 && x ..
orderby t1.Table1Id
group x by new {t1.Table1Id,t1.Name} into g
select new {
Table1Id = g.Key.Table1Id,
Name = g.Key.Name,
TheDate = g.Max(c => c.TheDate)
}

Related

pl/sql statement Trigger

Suppose we have the following two tables:
OrderHeader(OrderID, Odate, CustID, Total)
Order_Item(OrderID,ItemID, Qty, Subtotal)
Write a statement-level trigger that updates the Total in the orderHeader table with
the total value of the order_item records whenever an insert, update or delete event
occurs on the order_item table. For any update error, raise an exception.
So far I have written this:
create or replace TRIGGER SECURE_ORDER
AFTER INSERT OR DELETE OR UPDATE ON Order_Item
declare
sum1 Number;
BEGIN
SELECT SUM(Qty*Price) Into sum1 FROM Order_Item Inner join Item Using(ItemID) WHERE OrderID=:OLD.OrderID;
UPDATE OrderHeader set Total=sum1 where OrderID=:OLD.OrderID;
EXCEPTION
WHEN too_many_rows then
dbms_output.put_line('Too many rows');
WHEN no_data_found then
dbms_output.put_line('No Data Found');
WHEN others then
dbms_output.put_line('other error');
END;
It is not correct however as the question statement says I have to write a statement level trigger which doesn't give me acces to NEW and OLD keyword. I don't know how to go about doing this in a statement level trigger. Any help would be appreciated.
You can just use a single MERGE statement:
CREATE TRIGGER SECURE_ORDER
AFTER INSERT OR DELETE OR UPDATE ON Order_Item
BEGIN
MERGE INTO OrderHeader dst
USING (
SELECT COALESCE( oh.OrderID, o.OrderID ) AS OrderID,
COALESCE( SUM( o.Qty*i.Price ), 0 ) AS total
FROM OrderHeader oh
FULL OUTER JOIN Order_Item o
ON oh.OrderID = o.OrderID
LEFT OUTER JOIN Item i
ON ( o.ItemID = i.ItemID )
GROUP BY COALESCE( oh.OrderID, o.OrderID )
) src
ON ( src.OrderID = dst.OrderID )
WHEN MATCHED THEN
UPDATE SET total = src.total
WHEN NOT MATCHED THEN
INSERT ( OrderID, Total ) VALUES ( src.OrderID, src.Total );
END;
/
Then, if you have the tables:
CREATE TABLE Item (
ItemID NUMBER(10,0)
GENERATED ALWAYS AS IDENTITY
CONSTRAINT Item__ItemID__PK PRIMARY KEY,
Name VARCHAR2(20)
NOT NULL,
Price NUMBER(12,2)
NOT NULL
CONSTRAINT Item__Price_GTE_0__CHK CHECK ( Price >= 0 )
);
CREATE TABLE Order_Item (
OrderID INT
-- CONSTRAINT Order_Item__OrderID__FK REFERENCES Orders ( OrderID )
NOT NULL,
Qty INT
NOT NULL
CONSTRAINT Order_Item__Qty_GT_0__CHK CHECK ( Qty > 0 ),
ItemID INT
NOT NULL
CONSTRAINT Order_Item__ItemID__FK REFERENCES Item ( ItemId ),
CONSTRAINT Order_Item__OID__IID__PK PRIMARY KEY ( OrderID, ItemID )
);
CREATE TABLE OrderHeader (
OrderID INT
NOT NULL,
total NUMBER(14,2)
NOT NULL
);
Then if you:
INSERT INTO Item ( Name, Price ) VALUES ( 'Item 001', 1.00 );
INSERT INTO Item ( Name, Price ) VALUES ( 'Item 002', 2.00 );
INSERT INTO Item ( Name, Price ) VALUES ( 'Item 003', 2.50 );
INSERT INTO Order_Item ( OrderID, ItemID, Qty ) VALUES ( 1, 1, 3 );
INSERT INTO Order_Item ( OrderID, ItemID, Qty ) VALUES ( 1, 2, 1 );
INSERT INTO Order_Item ( OrderID, ItemID, Qty ) VALUES ( 1, 3, 2 );
The OrderHeader table contains:
SELECT * FROM OrderHeader;
ORDERID | TOTAL
------: | ----:
1 | 10
Then if you do:
UPDATE Order_Item
SET Qty = 8
WHERE OrderID = 1
AND ItemID = 1;
The OrderHeader table contains:
SELECT * FROM OrderHeader;
ORDERID | TOTAL
------: | ----:
1 | 15
Then if you do:
DELETE FROM Order_Item
WHERE ( OrderID, ItemID ) IN ( (1,2), (1,3) );
The OrderHeader table contains:
SELECT * FROM OrderHeader;
ORDERID | TOTAL
------: | ----:
1 | 8
And, finally, if you do:
DELETE FROM Order_Item;
The OrderHeader table contains:
SELECT * FROM OrderHeader;
ORDERID | TOTAL
------: | ----:
1 | 0
db<>fiddle here

Working out the Oracle Select Statement

what im trying to do is to find number of saving account at each branch, and display the number and branch address.
here is code :
create type address as object
(
street varchar2(20),
city varchar2(10),
p_code varchar2(8)
);
create type Branch as object
(
BId varchar2(3),--branch id
brAddress address,
bPhone int
);
create table tb_Branch of Branch
(
bid primary key
);
create type account as object
(
accNum varchar2(4), --pk
accType varchar2(8), -- check(current, saving)
balance number(8,2)
BId_ref ref BId
);
create tb_account of account
(
accNum primary key,
constraint accType_const check(accType IN ('current','savings'))
);`
Please help!
thanks!
Maybe the following example (Oracle 12c) will help you to find a solution ... (the TYPEs and TABLEs may need tweaking).
Types and tables
-- types
create type address_t as object (
street varchar2(20)
, city varchar2(10)
, postcode varchar2(8)
)
/
create type branch_t as object (
brid varchar2(64)
, braddress address_t
, brphone varchar2(24)
)
/
create type account_t as object (
accnum varchar2(4)
, acctype varchar2(8)
, balance number(12,2)
)
/
-- tables
create table branches (
branch branch_t
, constraint branch_pk primary key ( branch.brid )
);
create table accounts (
id number generated always as identity primary key
, account_details account_t
, constraint acc_type_check check(
account_details.acctype in ('current','savings')
)
, branchid references branches( branch.brid )
);
Some INSERTs (table BRANCHES)
insert into branches ( branch )
values (
branch_t( '66-20-67'
, address_t( '1 High St', 'Edinburgh', 'EH1 1AA' )
, '00441155700340' )
) ;
-- trying to insert this again
-- gives us
-- ORA-00001: unique constraint (...BRANCH_PK) violated -> PK constraint working
insert into branches ( branch )
values (
branch_t( '88-45-13'
, address_t( '2 Princes St', 'Edinburgh', 'EH2 2BB' )
, '00441156800900' )
) ;
-- The BRANCHES table contains:
SQL> select * from branches;
BRANCH(BRID, BRADDRESS(STREET, CITY, POSTCODE), BRPHONE)
---------------------------------------------------------------------------------------------------------------------------
BRANCH_T('66-20-67', ADDRESS_T('1 High St', 'Edinburgh', 'EH1 1AA'), '00441155700340')
BRANCH_T('88-45-13', ADDRESS_T('2 Princes St', 'Edinburgh', 'EH2 2BB'), '00441156800900')
Populate the ACCOUNTS table
begin
insert into accounts ( account_details, branchid )
values ( account_t ( '7890', 'savings', 123456.78 ), '66-20-67' ) ;
insert into accounts ( account_details, branchid )
values ( account_t ( '7891', 'savings', 222222.22 ), '66-20-67' ) ;
insert into accounts ( account_details, branchid )
values ( account_t ( '7892', 'savings', 333333.33 ), '88-45-13' ) ;
insert into accounts ( account_details, branchid )
values ( account_t ( '6789', 'current', 234567.89 ), '88-45-13' ) ;
end;
/
-- fails due to CHECK constraint
insert into accounts ( account_details, branchid )
values ( account_t ( '1234', 'standard', 4567.89 ), '66-20-67' ) ;
-- ORA-02290: check constraint (...ACC_TYPE_CHECK) violated
Query
/*
from your question:
" what im trying to do is
to find number of saving account at each branch,
and display the number and branch address "
*/
-- suggested query
select
A.account_details.acctype as acctype
, B.branch.brid as branchid
, B.branch.braddress.city as city
, count( * )
from branches B
join accounts A on B.branch.brid = A.branchid
where A.account_details.acctype = 'savings'
group by A.account_details.acctype
, B.branch.brid
, B.branch.braddress.city ;
ACCTYPE BRANCHID CITY COUNT(*)
-------- ---------- ---------- ----------
savings 88-45-13 Edinburgh 1
savings 66-20-67 Edinburgh 2

how to delete corresponding matching rows in Oracle SQL?

I'm trying to delete rows in a table only when there is a corresponding entry with a negative amount. The tricky part is there could be more positive than negative or more negative than positive.
value1 amt
12345 50
12345 50
12345 -50
12345 -50
abcde 40
abcde 40
abcde -40
11111 30
11111 -30
11111 -30
The result should be:
abcde 40
11111 -30
I have to apologize. I realized the posters data set was too simple. Here is a revised answer that I believe works.
Basically, you need to partition into pairs and then delete the pairs having sum() = 0.
create table t ( id varchar2(20), val number );
delete from t;
INSERT INTO t ( id, val ) values ( '12345', 50);
INSERT INTO t ( id, val ) values ( '12345', 50);
INSERT INTO t ( id, val ) values ( '12345', -50);
INSERT INTO t ( id, val ) values ( '12345', -50);
INSERT INTO t ( id, val ) values ( 'abcde', 40);
INSERT INTO t ( id, val ) values ( 'abcde', 40);
INSERT INTO t ( id, val ) values ( 'abcde', 20);
INSERT INTO t ( id, val ) values ( 'abcde', 40);
INSERT INTO t ( id, val ) values ( 'abcde', -40);
INSERT INTO t ( id, val ) values ( '11111', 30);
INSERT INTO t ( id, val ) values ( '11111', -30);
INSERT INTO t ( id, val ) values ( '11111', -30);
INSERT INTO t ( id, val ) values ( 'aaaaa', 10);
INSERT INTO t ( id, val ) values ( 'aaaaa', -30);
COMMIT;
MERGE INTO t
USING (WITH value_partition AS
(SELECT t.*,
ROW_NUMBER () OVER (PARTITION BY t.id, t.val ORDER BY ROWID) rn_in_value
FROM t)
SELECT sp.ROWID row_id,
sp.*,
CASE WHEN SUM (sp.val) OVER (PARTITION BY sp.id, ABS (sp.val), rn_in_value) = 0 THEN 'N' ELSE 'Y' END
keep_row
FROM value_partition sp) u
ON (t.ROWID = u.row_id
AND u.keep_row = 'N')
WHEN MATCHED THEN
UPDATE SET t.val = u.val
DELETE
WHERE u.keep_row = 'N';
SELECT * FROM t;

updating two column from select statement?

I am trying to update two columns from select statement, but I am getting error message that says
ORA-00927: missing equal sign
Please, can anyone tell me why ?
UPDATE table1 a
SET co1 ,co2 = (SELECT COUNT (*),
sum(cost)/4
FROM table2 b
WHERE a.customer_id = b.cust_info_customer_id
AND tariff_info = 2);
Since you didn't provide any input:
create table table1(
co1 number,
co2 number,
customer_id number
)
insert into table1 values (1,1, 1)
select * from table1
CO1 CO2 CUSTOMER_ID
-------------------
1 1 1
UPDATE table1 a
SET co1 = (
with table2 as (
select level cost, 1 cust_info_customer_id from dual connect by rownum < 5
)
SELECT COUNT (*)
FROM table2 b
WHERE a.customer_id = b.cust_info_customer_id
)
, co2 = (
with table2 as (
select level cost, 1 cust_info_customer_id from dual connect by rownum < 5
)
SELECT sum(cost)/4
FROM table2 b
WHERE a.customer_id = b.cust_info_customer_id
)
select * from table1
CO1 CO2 CUSTOMER_ID
-------------------
4 2.5 1

How do i turn this tables into an object-oriented table (object-relation) in Oracle

I have this table below in the picture that i want to create as an object-oriented table. I dont want the usual create table with relationships.... I just want to learn how to turn this table into an object-oriented table. Below is a picture of my tables and how are they connected:
CREATE TYPE A_TYPE AS OBJECT(
id INT,
col1 INT
);
/
CREATE TYPE A_REF_TABLE_TYPE AS TABLE OF REF A_TYPE;
/
CREATE TYPE B_TYPE AS OBJECT(
id INT,
col1 INT
);
/
CREATE TYPE B_REF_TABLE_TYPE AS TABLE OF REF B_TYPE;
/
CREATE TYPE C_TYPE AS OBJECT(
id INT,
a_list A_REF_TABLE_TYPE,
b_list B_REF_TABLE_TYPE,
col1 INT
);
/
CREATE TABLE A_TAB OF A_TYPE(
ID PRIMARY KEY
);
CREATE TABLE B_TAB OF B_TYPE(
ID PRIMARY KEY
);
CREATE TABLE C_TAB OF C_TYPE(
ID PRIMARY KEY
)
NESTED TABLE a_list STORE AS c_a_lists
NESTED TABLE b_list STORE AS c_b_lists;
INSERT INTO A_TAB VALUES( A_TYPE( 1, 3 ) );
INSERT INTO A_TAB VALUES( 2, 4 );
INSERT INTO B_TAB VALUES ( B_TYPE( 1, 7 ) );
INSERT INTO B_TAB VALUES ( 2, 2 );
INSERT INTO B_TAB VALUES ( 3, 10 );
INSERT INTO C_TAB VALUES (
1,
A_REF_TABLE_TYPE(
( SELECT REF(a) FROM A_TAB a WHERE ID = 2 ) -- Single value
),
( -- Multiple values
SELECT CAST( COLLECT( REF(b) ) AS B_REF_TABLE_TYPE )
FROM TAB_B b
WHERE ID IN ( 1, 3 )
),
42
);
INSERT INTO C_TAB VALUES (
2,
NULL, -- Unknown
B_REF_TABLE_TYPE(), -- No values
54
);
Output:
SELECT * FROM C_TAB;
ID A_LIST B_LIST COL1
-- ------------------------------- --------------------------------------------- ----
1 A_REF_TABLE_TYPE( A_TYPE(2,4) ) B_REF_TABLE_TYPE( B_TYPE(1,7), B_TYPE(3,10) ) 42
2 (null) B_REF_TABLE_TYPE() 54

Resources