How to join two datatable for dynamic column in LINQ - linq

I have a two datatable dt1 and dt2 (which are generated in runtime) and i have to apply inner join query on this table.(EmpId is same in both table)
but the no of coloumns and their names are dynamic which are depends upon databse.
both table contains same coloumn name like table 1 have coloumn this table contains leave taken by employee "p" .he have not taken any sickleave so value is null.
EmpId Empname SickLeave Casual Leave
1 P 1
and table two have values like
EmpId Empname SickLeave Casual Leave
1 P 5 5
this table contain total leave given by a copmany to a employee (Max leave)
i have to join this query and show result like this
EmpId Empname SickLeave Casual Leave
1 P 0/5 1/5
so i want to know how can i join this two datable and show result like this using Ef and LINQ. (no of leave given two i.e sick leave ,casual leave but it may be three or 2 or 4 depend upon databese and its name also can be chage accoding to databse)
if any one have an idea please guide me

If you really need dynamic Linq to entities then
OPTION A) string to lambda
Dynamic Expressions and Queries in LINQ
System.Linq.Dynamic can be found at following links
http://msdn.microsoft.com/en-US/vstudio/bb894665.aspx
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
http://www.scottgu.com/blogposts/dynquery/dynamiclinqcsharp.zip
How to convert a String to its equivalent LINQ Expression Tree?
OPTION B) Build expression trees
A more thorough approach is to build expression trees. Build expressions trees with code found here:
http://msdn.microsoft.com/en-us/library/system.linq.expressions.aspx
Dynamic LINQ and Dynamic Lambda expressions?

Related

Relational algebra - recode column values

Suppose I have a table 'animals' whose rows represent different animals and there is a column species that might have values like 'cat', 'dog', 'horse', 'cow' etc. Suppose I am only interested in whether the animal is a dog or not. In sql (at least in MySQL) I am able to make a query like select (species='dog') as isDog from animals to return 1 for dogs and 0 otherwise. How can I express this in RA? It is not selecting because we are not limiting rows. Can I use project operator even though my expression (species='dog') is not an attribute as such? Or how should I deal with this?
EDIT:
I want to achieve what would result by using the project-operator on a column that does not exist but is rather based on the truth value of a statement. For example the table animals containing rows with just one column 'species' having rows: cat, dog, horse, cow. I need the boolean value that could be renamed to 'isDog' that would result in values 0,1,0,0 (1=true, 0=false). I get this information in MySQL by selecting (species='dog') as isDog and I wonder if it is valid RA to use the project-operator with (species='dog') to pick such a dynamically created column, or is there some other way to deal with this?
TL;DR To introduce specific values into a relational algebra expression you have to have a way to write table literals. Usually the necessary operators are not made explicit, but on the other hand algebra exercises frequently use some kind of notation for example values.
For your case using the simplest additional relations (with an ad hoc table literal notation similar to SQL VALUES):
(restrict SPECIES=dog Animals) natural join TABLE{ISDOG}{<1>}
union (restrict SPECIES<>dog Animals) natural join TABLE{ISDOG}{<0>}
If you want a reference to a relational algebra with an operator for general calculations see author Chris Date's EXTEND operator and his classic textbook An Introduction to Database Systems, 8th Edition.
(More generally: To output a table with rows with new columns with values that are arbitrary functions of values in input rows we have to have access to tables corresponding to operators. Either we use a table literal or we assume a boolean function and use its name as a table name.)
But it turns out that the relational model was designed so that:
Every algebra operator corresponds to a certain logic operator.
NATURAL JOIN & AND
RESTRICTtheta & ANDtheta
UNION & OR
MINUS & AND NOT
PROJECTall butC & EXISTS C
etc
Every nested algebra expression corresponds to a certain nested logic expression.
Animals &
"animal named NAME is AGE years old ... and is of species SPECIES"
restrict SPECIES=dog Animals &
"animal named NAME is AGE years old ... and is of species SPECIES" AND SPECIES=dog
A proposition is a statement. A predicate is a statement template. If each base table holds the rows that make a true proposition from a predicate parameterized by its columns then a query holds the rows that make a true proposition from a corresponding predicate parameterized by its columns.
-- table of rows where
animal named NAME is AGE years old ... and is of species SPECIES
Animals
-- table of rows where
animal named NAME is AGE years old ... and is of species SPECIES
AND if SPECIES=dog then ISDOG=1 ELSE ISDOG=0
-- ie rows where
animal named NAME is AGE years old ... and is of species SPECIES
AND (SPECIES=dog AND ISDOG=1 OR SPECIES<>DOG AND ISDOG=0)
-- ie rows where
animal named NAME is AGE years old ... and is of species SPECIES
AND SPECIES=dog AND ISDOG=1
OR animal named NAME is AGE years old ... and is of species SPECIES
AND SPECIES<>dog AND ISDOG=0
(restrict SPECIES=dog Animals) natural join TABLE{ISDOG}{<1>}
union (restrict SPECIES<>dog Animals) natural join TABLE{ISDOG}{<0>}
So you can just use logic, the language of precision in engineering (including software-), science (including computer-) and mathematics, to describe your result tables.
-- table of rows where
animal named NAME is AGE years old ... and is of species SPECIES
AND ISDOG=(if SPECIES=dog then 1 else 0)
So you can use table expressions and/or logic expressions in specifications, whichever happens to be clearer, on a (sub)expression-by-(sub)expression basis.
Animals
natural join
table of rows where if SPECIES=dog THEN ISDOG=1 ELSE ISDOG=0
(The table corresponding to that IF expression has a row for every string, and the 'dog' row is the only one with a 1.)
(Nb SQL ON & WHERE have this form of a table on the left and predicate with functions on the right.)
An algebra expression calculates the rows that satisfy its corresponding logic expression.
It might not be obvious to you what
equivalent relation expressions correspond to what equivalent logic expressions and vice versa. But all that matters is that your clients understand the algebra and/or logic in the specification and your programmers can write an equivalent SQL expression.
Instead of so natural joining a table representing arguments to a table representing a function, you can 1) cross join each one-row table holding a function result to the restriction of the argument table to rows that give that result then 2) union the cross joins.
(restrict SPECIES=dog Animals) natural join TABLE{ISDOG}{<1>}
union (restrict SPECIES<>dog Animals) natural join TABLE{ISDOG}{<0>}
See also: Is multiplication allowed in relational algebra?
Re querying relationally: Relational algebra for banking scenario
Re understanding the semantics of relational algebra & SQL (plus more links): Is there any rule of thumb to construct SQL query from a human-readable description?
PS SQL SELECT does things that projection does, but it also does other things that aren't projection, which get done in the algebra by rename, join and/or table literals. What you want isn't projection. It is called EXTEND by author Chris Date. I would advise anyone to use/reference Date's algebra. Although adding RESTRICT/WHERE and EXTEND on arbitrary logic expressions (wffs & terms) begs the question of how one deals with the logic expressions algebraically. This answer explains that/how you can always algebraically express the logic expressions given literal and/or operator tables.

Oracle - select statement alias one column and wildcard to get all remaining columns

New to SQL. Pardon me if this question is a basic one. Is there a way for me to do this below
SELECT COLUMN1 as CUSTOM_NAME, <wildcard for remaining columns as is> from TABLE;
I only want COLUMN1 appear once in the final result
There is no way to make that kind of dynamic SELECT list with regular SQL*.
This is a good thing. Programming gets more difficult the more dynamic it is. Even the simple * syntax, while useful in many contexts, causes problems in production code. The Oracle SQL grammar is already more complicated than most traditional programming languages, adding a little meta language to describe what the queries return could be a nightmare.
*Well, you could create something using Oracle data cartridge, or DBMS_XMLGEN, or a trick with the PIVOT clause. But each of those solutions would be incredibly complicated and certainly not as simple as just typing the columns.
This is about as close as you will get.
It is very handy for putting the important columns up front,
while being able to scroll to the others if needed. COLUMN1 will end up being there twice.
SELECT COLUMN1 as CUSTOM_NAME,
aliasName.*
FROM TABLE aliasName;
In case you have many columns it might be worth to generate a full column list automatically instead of relying on the * selector.
So a two step approach would be to generate the column list with custom first N columns and unspecified order of the other columns, then use this generated list in your actual select statement.
-- select comma separated column names from table with the first columns being in specified order
select
LISTAGG(column_name, ', ') WITHIN GROUP (
ORDER BY decode(column_name,
'FIRST_COLUMN_NAME', 1,
'SECOND_COLUMN_NAME', 2) asc) "Columns"
from user_tab_columns
where table_name = 'TABLE_NAME';
Replace TABLE_NAME, FIRST_COLUMN_NAME and SECOND_COLUMN_NAME by your actual names, adjust the list of explicit columns as needed.
Then execute the query and use the result, which should look like
FIRST_COLUMN_NAME, SECOND_COLUMN_NAME, OTHER_COLUMN_NAMES
Ofcourse this is overhead for 5-ish columns, but if you ever run into a company database with 3 digit number of columns, this can be interesting.

How to update a column with concatenate of two other column in a same table

I have a table with 3 columns a, b and c. I want to know how to update the value of third column with concatenate of two other columns in each row.
before update
A B c
-------------
1 4
2 5
3 6
after update
A B c
-------------
1 4 1_4
2 5 2_5
3 6 3_6
How can I do this in oracle?
Use the concatentation operator ||:
update mytable set
c = a || '_' || b
Or better, to avoid having to rerun this whenever rows are inserted or updated:
create view myview as
select *, a || '_' || b as c
from mytable
Firstly, you are violating the rules of normalization. You must re-think about the design. If you have the values in the table columns, then to get a computed value, all you need is a select statement to fetch the result the way you want. Storing computed values is generally a bad idea and considered a bad design.
Anyway,
Since you are on 11g, If you really want to have a computed column, then I would suggest a VIRTUAL COLUMN than manually updating the column. There is a lot of overhead involved with an UPDATE statement. Using a virtual column would reduce a lot of the overhead. Also, you would completely get rid of the manual effort and those lines of code to do the update. Oracle does the job for you.
Of course, you will use the same condition of concatenation in the virtual column clause.
Something like,
Column_c varchar2(50) GENERATED ALWAYS AS (column_a||'_'||column_b) VIRTUAL
Note : There are certain restrictions on its use. So please refer the documentation before implementing it. However, for the simple use case provided by OP, a virtual column is a straight fit.
Update I did a small test. There were few observations. Please read this question for a better understanding about how to implement my suggestion.

Oracle Select Query, Order By + Limit Results

I am new to Oracle and working with a fairly large database. I would like to perform a query that will select the desired columns, order by a certain column and also limit the results. According to everything I have read, the below query should be working but it is returning "ORA-00918: column ambiguously defined":
SELECT * FROM(SELECT * FROM EAI.EAI_EVENT_LOG e,
EAI.EAI_EVENT_LOG_MESSAGE e1 WHERE e.SOURCE_URL LIKE '%.XML'
ORDER BY e.REQUEST_DATE_TIME DESC) WHERE ROWNUM <= 20
Any suggestions would be greatly appreciated :D
The error message means your result set contains two columns with the same name. Each column in a query's projection needs to have a unique name. Presumably you have a column (or columns) with the same name in both EAI_EVENT_LOG and EAI_EVENT_LOG_MESSAGE.
You also want to join on that column. At the moment you are generating a cross join between the two tables. In other words, if you have a hundred records in EAI_EVENT_LOG and two hundred records EAI_EVENT_LOG_MESSAGE your result set will be twenty thousand records (without the rownum). This is probably your intention.
"By switching to innerjoin, will that eliminate the error with the
current code?"
No, you'll still need to handle having two columns with the same name. Basically this comes from using SELECT * on two multiple tables. SELECT * is bad practice. It's convenient but it is always better to specify the exact columns you want in the query's projection. That way you can include (say) e.TRANSACTION_ID and exclude e1.TRANSACTION_ID, and avoid the ORA-00918 exception.
Maybe you have some columns in both EAI_EVENT_LOG and EAI_EVENT_LOG_MESSAGE tables having identical names? Instead of SELECT * list all columns you want to select.
Other problem I see is that you are selecting from two tables but you're not joining them in the WHERE clause hence the result set will be the cross product of those two table.
You need to stop using SQL '89 implicit join syntax.
Not because it doesn't work, but because it is evil.
Right now you have a cross join which in 99,9% of the cases is not what you want.
Also every sub-select needs to have it's own alias.
SELECT * FROM
(SELECT e.*, e1.* FROM EAI.EAI_EVENT_LOG e
INNER JOIN EAI.EAI_EVENT_LOG_MESSAGE e1 on (......)
WHERE e.SOURCE_URL LIKE '%.XML'
ORDER BY e.REQUEST_DATE_TIME DESC) s WHERE ROWNUM <= 20
Please specify a join criterion on the dotted line.
Normally you do a join on a keyfield e.g. ON (e.id = e1.event_id)
It's bad idea to use select *, it's better to specify exactly which fields you want:
SELECT e.field1 as customer_id
,e.field2 as customer_name
.....

How do I show blank entries on a BIRT Table sub-group?

I am trying to create a table with two groups in a BIRT report.
I first group by year, and then by a criteria in a second column. Let's say this criteria is one of [A, B, C, D]. If there doesn't exist a criteria for a year, the default in BIRT is for it to be blank. For example, if 2011 didn't have any B or D criteria, my report would look like:
2010
----
A 1
B 2
C 3
D 4
2011
----
A 5
C 6
However, I want all the possible criteria to show up, even if they don't have any entries for a particular year.
I tried setting the property under advanced->section->show if blank = true, but that didn't do anything.
Any ideas?
(I am using birt 2.6.0)
The SQL query (connecting to a mysql datasource) is fairly simple:
SELECT year_field, decision_field, sales_field
FROM databaseName
The report is http://bit.ly/9SDbNI
And produces a report like:
As I commented earlier, this is a dataset issue, not a BIRT issue. The issue is that the dataset does not include rows where there were no sales for those decision codes, in those years.
I was rather hoping there would be separate tables for the years and decision codes, but it looks as though there's a single table for everything. Therefore, I suggest the following query (based on the query in the rptdesign file, rather than the question):
select y.year_field, d.decision_field, t.sales_field
from
(select distinct year_field from databaseTable) y
cross join (select distinct decision_field from databaseTable) d
left join databaseTable t
on y.year_field = t.year_field and d.decision_field = t.decision_field
Also, change the definition of the Count column to be a count of the sales field, rather than the decision field.
I noticed that you are using MySql. Use SELECT IFNULL(<MyCol>,0) from my_table; to replace the null values with 0.

Resources