Get data from both tables in LINQ - linq

I am trying to fetch an IP-address column which is present in both tables, A and B. Table A has many IP-adresses and a specific IP-address which is not present in table B. I want distinct IP-addresses from both the tables. That means I want all IP-adresses from table A which are not present in table B, plus all IP-adresses from table B which are not present in table A. I am trying the below code which is only giving me the IP-adresses which are not present in table B. Please help.
var ips= (from a in CS.A
where !CS.B.Any(f => f.IPAddress == a.IPAddress)
select a.IPAddress).Distinct();

You can simply use this
var ips= ((from a in CS.A
where !CS.B.Any(f => f.IPAddress == a.IPAddress)
select a.IPAddress).Distinct()).Union((from b in CS.B
where !CS.A.Any(f => f.IPAddress == b.IPAddress)
select b.IPAddress).Distinct());

You can just Concat both IP columns and group by the IPs.
Then only select the groups which have a count of 1 (= IP only occurs in one table)
var res =
(from ip in CS.A.Select(x => x.ip)
.Distinct()
.Concat(CS.B.Select(x => x.ip).Distinct())
group ip by ip into grp
where grp.Count() == 1
select grp.Key).ToList();
You can test this with the following example:
var x1 = Enumerable.Range(0, 20);
var x2 = Enumerable.Range(5, 20);
var res =
(from ip in x1.Select(x => x).Distinct().Concat(x2.Select(x => x).Distinct())
group ip by ip into grp
where grp.Count() == 1
select grp.Key).ToList();
res.ForEach(Console.WriteLine);

My first suggestion would be to use a store procedure to achieve that. Something along the lines of:
SELECT tblA.ip, tblB.ip FROM Table1 tblA
INNER JOIN Table2 tblB
ON 1=1
GROUP BY tblA.ip
the "ON" here will give you a condition that is always true.
Roughly the same query should work with linq as well. Experiment :-)
edit
UNION is also an option, however most not as easily read by non-SQL developers.
Select distinct cmnTbl.ip from (SELECT tblA.ip from Table1 tblA UNION SELECT tblB.ip from Table1) cmnTbl

Related

ORA-00918 returns from stored procedure but it works executing a query in SQL Page

I'm trying return a list from db but it gives me Error "ORA-00918: column ambiguously defined".
When I execute this query inside new SQL page, it returns true list. However, when I write it in a package as stored procedure, it returns ORA-00918 and package goes invalid status.
What is the reason for this difference?
select distinct c.customer_no, m.title, c.group_id, g.name, c.pricelist_id, p.name from db.customer c
join db.pricelist p on c.pricelist_id = p.pricelist_id
join db.master m on c.customer_no = m.customer_no
join db.group g on c.group_id = g.id
where (c.customer_no = pn_customer_no or pn_customer_no=-1)
and (c.group_id = pn_group_no or pn_group_no=-1)
and (c.pricelist_id = pn_pricelist_no or pn_pricelist_no=-1)
and (c.kom_type = ps_kom_tip)
order by c.customer_no asc
You are selecting the columns:
select distinct
c.customer_no,
m.title,
c.group_id,
g.name, -- NAME column
c.pricelist_id,
p.name -- NAME column
When you run the query in SQL/Plus or SQL Developer (or another IDE) it will output the columns:
CUSTOMER_NO TITLE GROUP_ID NAME PRICELIST_ID NAME1
and will rename the second NAME column to NAME1.
In the PL/SQL scope, it will not do this and will try to handle the two columns with the names you have given (i.e. the same names), fail and return ORA-00918.
You need to give one (or both) column an alias so they have distinct names.
New SQL page assigns your dublicate columns new temporary column names.
But stored procedures add your values a list matched column names.
Therefore, two columns have same names, it confuses which name should desired name.
Like bundle, your column name will be key to learn value and value will be value.
You should change one of them p.name or g.name or both of them.
select distinct c.customer_no, m.isim_unvan, c.group_id, g.name as groupName, c.pricelist_id, p.name as tarifeName from db.customer c
join db.pricelist p on c.pricelist_id = p.pricelist_id
join db.master m on c.customer_no = m.musteri_no
join db.group g on c.group_id = g.id
where (c.customer_no = pn_customer_no or pn_customer_no=-1)
and (c.group_id = pn_group_no or pn_group_no=-1)
and (c.pricelist_id = pn_pricelist_no or pn_pricelist_no=-1)
and (c.kom_type = ps_kom_tip)
order by c.customer_no asc

Oracle 11g Count query slowness

I have written one query which provides me a count of item type using group by.
The select query if I fire without group up and count provides results in less than a second on sql developer.
However count query runs for ever that I have to kill the process.
Below is the query ..
WITH permList
AS (SELECT user_perm_level,
item_category,
active
FROM usr_perm_levels
WHERE usr_pk = '7'
UNION ALL
SELECT home_key,
'ALL',
0
FROM user_home_list
WHERE usr_pk = 7
UNION ALL
SELECT home_key,
'UYT',
0
FROM user_home_list
WHERE usr_pk = 7
UNION ALL
SELECT home_key,
'ABR',
0
FROM user_home_list
WHERE usr_pk = 7),
list1
AS (SELECT a.parent_home_key,
b.item_category
FROM user_hier a
INNER JOIN indhome b
ON a.child_home_key = b.user_perm_level),
list2
AS ((SELECT oh.child_home_key,
u.item_category
FROM indhome U
INNER JOIN user_hier oh
ON u.user_perm_level = oh.parent_home_key
AND u.active = 1)
UNION ALL
SELECT user_perm_level,
item_category
FROM indhome)
SELECT type,
Count(*)
FROM inventory
WHERE is_available = 0
AND active = 1
AND EXISTS (SELECT 0
FROM inventory_auth c
WHERE EXISTS (SELECT 0
FROM orglist1
WHERE c.user_perm_level = orglist1.parent_home_key
AND c.item_category =
orglist1.item_category
AND c.active = 1)
OR EXISTS (SELECT 0
FROM orglist2
WHERE c.user_perm_level = orglist2.child_home_key
AND c.item_category =
orglist2.item_category)
AND inventory.item_key = c.item_key
AND inventory.item_category = c.item_category)
GROUP BY type;
In explain plan I see that Cost of group by clause is 145297221173.
Now here inventory table has 10 million records and the exists block which works around inventory table also runs into 15 million records.
Where as views permList, list1 and list2 have records only in 100s.
I have tried various combination but none of them seems to bring better performance. Such as I have tried inner join between inventory and inner query with exists clause but that doesn't help much.

oracle procedure cursor query when case statement

CURSOR BULKUPDATE IS
SELECT SUM(B.ACCOUNT_BALANCE) AS ACCOUNT_BALANCE,C.CIF AS CIF_ID FROM _ACCOUNTS_STAGING2 B JOIN _RELATION_STAGING2 C
ON B.ACCOUNT_IDENTIFICATION_NUMBER = C.ACCOUNT_IDENTIFICATION_NUMBER AND B.SOURCEID=C.SOURCEID JOIN _CUSTOMER_STAGING2 A ON A.CIF=C.CIF AND A.SOURCEID=C.SOURCEID WHERE C.ROLE_ON_ACCOUNT IN
(Select Rollonaccount From _Roleaccount_Master Where Aggregatebalance='Y')
And upper(B.Scheme_Type) In (Select Scheme_Type From _Schema_Type_Master Where
Depository_Account = 'Y') Group By C.Cif;
Rec_Bulkupdate Bulkupdate%Rowtype;
I am using this query to sum account balances based on different cif and source. The question is I want to calculate four different types of sum on the basis of _Schema_Type_Master. For example I want to check now current_account='Y' instead of Depository_Account='Y'
_ACCOUNTS_STAGING2 B JOIN _RELATION_STAGING2 C
ON B.ACCOUNT_IDENTIFICATION_NUMBER = C.ACCOUNT_IDENTIFICATION_NUMBER AND B.SOURCEID=C.SOURCEID JOIN _CUSTOMER_STAGING2 A ON A.CIF=C.CIF AND A.SOURCEID=C.SOURCEID WHERE C.ROLE_ON_ACCOUNT IN
(Select Rollonaccount From _Roleaccount_Master Where Aggregatebalance='Y')
And upper(B.Scheme_Type) In (Select Scheme_Type From _Schema_Type_Master Where
current_account='Y') Group By C.Cif;
Rec_Bulkupdate Bulkupdate%Rowtype;
Is there any way or do I need to write four different cursors for that??
You can remove dipository_account='Y' and current_account='Y' and use case in select as -
SELECT SUM(CASE WHEN Depository_Account = 'Y' THEN B.ACCOUNT_BALANCE ELSE 0 END) AS DIPOSITORY_ACCOUNT_BALANCE,
SUM(CASE WHEN current_account = 'Y' THEN B.ACCOUNT_BALANCE ELSE 0 END) AS CURRENT_ACCOUNT_BALANCE
and then rest of your code. You will get two different columns for sum of Depository account and Current account.
And if filter for dipository_account='Y' and current_account='Y' is required, then use them in where condition with or operator :
AND (dipository_account='Y' or current_account='Y')

How do I write a LINQ query to combine multiple rows into one row?

I have one table, 'a', with id and timestamp. Another table, 'b', has N multiple rows referring to id, and each row has 'type', and "some other data".
I want a LINQ query to produce a single row with id, timestamp, and "some other data" x N. Like this:
1 | 4671 | 46.5 | 56.5
where 46.5 is from one row of 'b', and 56.5 is from another row; both with the same id.
I have a working query in SQLite, but I am new to LINQ. I dont know where to start - I don't think this is a JOIN at all.
SELECT
a.id as id,
a.seconds,
COALESCE(
(SELECT b.some_data FROM
b WHERE
b.id=a.id AND b.type=1), '') AS 'data_one',
COALESCE(
(SELECT b.some_data FROM
b WHERE
b.id=a.id AND b.type=2), '') AS 'data_two'
FROM a first
WHERE first.id=1
GROUP BY first.ID
you didn't mention if you are using Linq to sql or linq to entities. However following query should get u there
(from x in a
join y in b on x.id equals y.id
select new{x.id, x.seconds, y.some_data, y.type}).GroupBy(x=>new{x.id,x.seconds}).
Select(x=>new{
id = x.key.id,
seconds = x.Key.seconds,
data_one = x.Where(z=>z.type == 1).Select(g=>g.some_data).FirstOrDefault(),
data_two = x.Where(z=>z.type == 2).Select(g=>g.some_data).FirstOrDefault()
});
Obviously, you have to prefix your table names with datacontext or Objectcontext depending upon the underlying provider.
What you want to do is similar to pivoting, see Is it possible to Pivot data using LINQ?. The difference here is that you don't really need to aggregate (like a standard pivot), so you'll need to use Max or some similar method that can simulate selecting a single varchar field.

How do I return a table in LINQ that relies on a join/subquery?

I need the fields in 1 table contingent on 1 property matching rows in another table.
I can write this query in SQL with a subquery as such:
SELECT *
FROM Table1
WHERE Property1 IN
(
SELECT Property1
FROM Table2
WHERE Property0 = 1
)
But I read here that it's less complicated and just as easy to write with a join, which I did. However, so far I'm unable to return just Table1 as I'd like since I'm using a join, which if I'm not mistaken, requires me to create this anonymous type, as below. What I did here works (I created another object with the same properties of Table1 I need), but I can't help thinking there's a better way to do this.
Table1.Join(Table2, t1 => t1.Property1, t2 => t2.Property1, (t1, t2) => new
{
t1.Property1,
t1.Property2,
t1.Property3
})
.Select(ob => new UnnecessaryObject
{
Property1 = ob.Property1,
Property2 = ob.Property2,
Property3 = ob.Property3
}
I also tried just creating a Table1 in the .Select part, but I got an error about explicit construction not being allowed.
Just to clarify, I'd like to be able to return the IQueryable of type Table1, which it seems like I ought to be able to do without having to create UnnecessaryObject...but I'm still pretty new to LINQ, so I'd appreciate any help you can offer. Thanks in advance.
You could just do:
from t1 in table1
join t2 in table2 on t1.property1 equals t2.property1
select t1;
That would return a collection of table1 objects. This assumes from your example table1 is a collection of table1 objects and table2 is a collection of table2 objects.
The best translation of your original query I can come up with is:
from item in context.Table1
where context.Table2
.Where(x => x.Property0 == 0)
.Any(x => x.Property1 == item.Property1)
select item
This selects all items from Table1, where there's an item with matching Property1 and Property0 == 0 from Table2
It can also be solved with a join indeed. To get an efficient join, you need to have a relation between the two tables. Then you can do something like assuming the relation is called RelatedItems:
from item in context.Table1
join relatedItem in item.RelatedItems
on item.Property1 equals relatedItem.Property
where relatedItem.Property0 == 0
select item
This is equivalent to the SQL:
SELECT *
FROM Table1
JOIN Table2 ON Table1.Property1 = Table2.Property1
WHERE Table2.Property0 = 0

Resources