Translating SQL to lambda expression - asp.net

How can I translate this to a lambda expression? Can anyone please help?
SELECT
p.*
FROM
db.MainProduct p
WHERE
p.id IN (SELECT ms.MainProductId
FROM db.MainProductToSupplierProduct ms)
AND (p.description LIKE '%' + #filter + '%'
OR Coalesce(#filter,'') = '')

Or in query syntax:
var ans = from p in db.MainProduct where (from ms in db.MainProductToSupplierProduct select ms.MainProductId).Contains(p.id) && (filter == "" || p.description.Contains(filter)) select p;
Not sure that is the most efficient way, a less literal translation would use a join:
var ans = from p in db.MainProduct join ms in db.MainProductToSupplierProduct on p.id equals ms.MainProductId where filter == "" || p.description.Contains(filter) select p;
This is a left semi join and the best way to implement that is probably an EXISTS in SQL - it may be faster than join:
var ans = from p in db.MainProduct where db.MainProductToSupplierProduct.Any(ms => ms.MainProductId == p.id) && (filter == "" || p.description.Contains(filter)) select p;

Below code can help you out
var filteredMainProduct= MainProduct.Where(t => MainProductToSupplierProduct.Any(z => z.MainProductId == t.id) && #filter != null ? t.description.Contains(#filter) : t.FareBasisDescription.Contains(""));

Related

How to build or condition on datasorce in the code?

I have two tables. Lets call them Table1 and Table2. I need to create in the code query like.
Select * from Table1
exists join Table2 where
Table1.Key == Table2.Key &&
(Table1.A == '1' || Table2.C == '2')
So to transfer to code I tried:
Query q;
QueryBuildDataSource qbd;
QueryBuildDataSource ofQbds;
QueryBuildRange qbr;
str range;
Table1 test;
QueryRun qr;
q = new Query();
qbd = q.addDataSource(tableNum(Table1));
qbd .name('Table1');
ofQbds = qbd.addDataSource(tableNum(Table2));
ofQbds.name('Table2');
ofQbds.addLink(fieldNum(Table1, Key), fieldNum(Table2, Key));
ofQbds.joinMode(JoinMode::InnerJoin);
range = strFmt('%1.%2 == %3 OR %4.%5 == %6', qbd.name(), 'A', '1',
ofQbds.name(), 'C', '5');
info(range);
ofQbds.addRange(fieldName2id(tableNum(Table1 ), 'A')).value(range);
qr = new QueryRun(q);
while (qr.next())
{
test = qr.get(test.TableId);
info(test.A + ','+test.Key);
}
info('done');
But the or condition does not work properly.
For example If I have values
Table1
A,Key
1,1
2,2
3,3
Table2
C,Key
2,2
I would expect 2 results from Table1
1,1
2,2
but I get only the first one
Message
Table1.A == 1 OR Table2.C == 2
2,2
done
I tried different joinModes and switching || and OR but nothing I tried yet works.
What I need to change to be able to have or condition in the code?
Try changing this line:
range = strFmt('%1.%2 == %3 OR %4.%5 == %6', qbd.name(), 'A', '1', ofQbds.name(), 'C', '5');
to
range = strFmt('((%1.%2 == %3) || (%4.%5 == %6))', qbd.name(), 'A', '1', ofQbds.name(), 'C', '5');
Don't use sql "or", instead use the x++ "||"
Edit: see http://www.axaptapedia.com/Expressions_in_query_ranges for more information.
Edit 2: This code executes for me in the desired fashion. I would recommend using the most up to date compile-time functions such as tableNum() and fieldNum() etc.
Query q;
QueryBuildDataSource qbd;
QueryBuildDataSource ofQbds;
QueryBuildRange qbr;
str range;
QueryRun qr;
CustTable custTable;
CustGroup custGroup;
q = new Query();
qbd = q.addDataSource(tableNum(CustTable));
ofQbds = qbd.addDataSource(tableNum(CustGroup));
ofQbds.addLink(fieldNum(CustTable, CustGroup), fieldNum(CustGroup, CustGroup));
ofQbds.joinMode(JoinMode::InnerJoin);
range = strFmt('((%1.%2 == %3) || (%4.%5 == %6))',
tableStr(CustTable),
fieldStr(CustTable, AccountNum),
'000001',
tableStr(CustGroup),
fieldStr(CustGroup, CustGroup),
'UAC');
info(range);
ofQbds.addRange(fieldNum(CustTable, AccountNum)).value(range);
qr = new QueryRun(q);
while (qr.next())
{
custTable = qr.get(tableNum(CustTable));
info(custTable.AccountNum + ',' +custTable.CustGroup);
}

pl/sql : execute immediate update?

V_SQL4 := 'UPDATE EMP_TABLE m
Set m.name = mft.name,
m.age = mft.age,
m.dept = mft.dept,
Where m.id = mft.id and
(m.name != mft.name Or
m.age != mft.age Or
m.dept != mft.dept )';
DBMS_OUTPUT.PUT_LINE(V_SQL4);
EXECUTE IMMEDIATE V_SQL4;
How and where to declare the temporary table EMP_TMPas mft in the statement?
If i look into the requirement i dont see requirment of PL/SQL in
this. A better approach woould be using Merge. I have illuistrated an
example below. If Dynamic SQL is not hard and bound you can use this
too. Let me know if this helps.
MERGE INTO EMP_TABLE m USING EMP_TMP mft
ON (m.id = mft.id AND (m.name != mft.name OR m.age != mft.age OR m.dept != mft.dept))
WHEN MATCHED THEN
UPDATE SET
m.name = mft.name,
m.age = mft.age,
m.dept = mft.dept;
This SO post has an answer to a similar question.
In your case, the query would transform as below
V_SQL4 := 'UPDATE EMP_TABLE m
SET (name, age, dept) = (SELECT mft.name
,mft.age
,mft.dept
FROM EMP_TMP mft
WHERE m.id = mft.id
AND m.name != mft.name Or
AND m.age != mft.age Or
AND m.dept != mft.dept
)
WHERE EXISTS (
SELECT 1
FROM EMP_TMP mft
WHERE m.id = mft.id
)';

Entity Framework query joins and group by issue

Please correct the query
IN PL/SQL
SELECT a.MENU_ID, a.menu_label, a.menu_value
FROM tbl_ims_menu a, TBL_IMS_ROLE_ASSIGNED_MENU b,TBL_IMS_USER_ROLE_PRIVILEGES c
WHERE a.menu_id = b.menu_id AND b.urole_id = c.granted_role
AND c.user_id = '3' AND a.menu_master <> '0'
AND a.menu_status = 'Active'
GROUP BY a.menu_id, a.menu_label, a.menu_value
query is working fine there is some issue when rewrite in Entity framework
check the following query
List<TBL_IMS_MENU> listSubMenu = (from m in db.TBL_IMS_MENU
join ra in db.TBL_IMS_ROLE_ASSIGNED_MENU on m.MENU_ID
equals ra.MENU_ID
join rp in db.TBL_IMS_USER_ROLE_PRIVILEGES on ra.UROLE_ID
equals rp.GRANTED_ROLE
where rp.USER_ID == UserID
group m by m.MENU_ID
into g select g).ToList();
if I used Var instead of List then how to fire loop?
I think you need to remove your join statements - and just use the where like you do in raw SQL query:
var qry = (from a in db.TBL_IMS_MENU
from b in db.TBL_IMS_ROLE_ASSIGNED_MENU
from c in db.TBL_IMS_USER_ROLE_PRIVILEGES
where c.USER_ID == UserID
where b.UROLE_ID == c.GRANTED_ROLE
where a.MENU_ID == b.MENU_ID
where a.menu_status == "Active"
where a.menu_master != "0"
select a)
.GroupBy(c => c.menu_id)
.ThenBy(c => c.menu_label)
.ThenBy(c => c.menu_value)
.ToList();
Try something like this:
var listSubMenu = (from m in db.TBL_IMS_MENU
join ra in db.TBL_IMS_ROLE_ASSIGNED_MENU on m.MENU_ID
equals ra.MENU_ID
join rp in db.TBL_IMS_USER_ROLE_PRIVILEGES on ra.UROLE_ID
equals rp.GRANTED_ROLE
where rp.USER_ID == UserID
group m by new { m.MENU_ID, m.menu_label, m.menu_value }
into g select g).ToList();
foreach(var groupItem in listSubMenu)
{
// go through groups like this - groupItem.Key.MENU_ID
foreach(var menuItem in grouItem)
{
//go through each item in group like this - menuItem.GRANTED_ROLE
}
}

How to get a list of column names

Is it possible to get a row with all column names of a table like this?
|id|foo|bar|age|street|address|
I don't like to use Pragma table_info(bla).
SELECT sql FROM sqlite_master
WHERE tbl_name = 'table_name' AND type = 'table'
Then parse this value with Reg Exp (it's easy) which could looks similar to this: [(.*?)]
Alternatively you can use:
PRAGMA table_info(table_name)
If you are using the command line shell to SQLite then .headers on before you perform your query. You only need to do this once in a given session.
You can use pragma related commands in sqlite like below
pragma table_info("table_name")
--Alternatively
select * from pragma_table_info("table_name")
If you require column names like id|foo|bar|age|street|address, basically your answer is in below query.
select group_concat(name,'|') from pragma_table_info("table_name")
Yes, you can achieve this by using the following commands:
sqlite> .headers on
sqlite> .mode column
The result of a select on your table will then look like:
id foo bar age street address
---------- ---------- ---------- ---------- ---------- ----------
1 val1 val2 val3 val4 val5
2 val6 val7 val8 val9 val10
This helps for HTML5 SQLite:
tx.executeSql('SELECT name, sql FROM sqlite_master WHERE type="table" AND name = "your_table_name";', [], function (tx, results) {
var columnParts = results.rows.item(0).sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').split(','); ///// RegEx
var columnNames = [];
for(i in columnParts) {
if(typeof columnParts[i] === 'string')
columnNames.push(columnParts[i].split(" ")[0]);
}
console.log(columnNames);
///// Your code which uses the columnNames;
});
You can reuse the regex in your language to get the column names.
Shorter Alternative:
tx.executeSql('SELECT name, sql FROM sqlite_master WHERE type="table" AND name = "your_table_name";', [], function (tx, results) {
var columnNames = results.rows.item(0).sql.replace(/^[^\(]+\(([^\)]+)\)/g, '$1').replace(/ [^,]+/g, '').split(',');
console.log(columnNames);
///// Your code which uses the columnNames;
});
Use a recursive query. Given
create table t (a int, b int, c int);
Run:
with recursive
a (cid, name) as (select cid, name from pragma_table_info('t')),
b (cid, name) as (
select cid, '|' || name || '|' from a where cid = 0
union all
select a.cid, b.name || a.name || '|' from a join b on a.cid = b.cid + 1
)
select name
from b
order by cid desc
limit 1;
Alternatively, just use group_concat:
select '|' || group_concat(name, '|') || '|' from pragma_table_info('t')
Both yield:
|a|b|c|
The result set of a query in PHP offers a couple of functions allowing just that:
numCols()
columnName(int $column_number )
Example
$db = new SQLIte3('mysqlite.db');
$table = 'mytable';
$tableCol = getColName($db, $table);
for ($i=0; $i<count($tableCol); $i++){
echo "Column $i = ".$tableCol[$i]."\n";
}
function getColName($db, $table){
$qry = "SELECT * FROM $table LIMIT 1";
$result = $db->query($qry);
$nCols = $result->numCols();
for ($i = 0; $i < $ncols; $i++) {
$colName[$i] = $result->columnName($i);
}
return $colName;
}
$<?
$db = sqlite_open('mysqlitedb');
$cols = sqlite_fetch_column_types('form name'$db, SQLITE_ASSOC);
foreach ($cols as $column => $type) {
echo "Column: $column Type: $type\n";
}
Using #Tarkus's answer, here are the regexes I used in R:
getColNames <- function(conn, tableName) {
x <- dbGetQuery( conn, paste0("SELECT sql FROM sqlite_master WHERE tbl_name = '",tableName,"' AND type = 'table'") )[1,1]
x <- str_split(x,"\\n")[[1]][-1]
x <- sub("[()]","",x)
res <- gsub( '"',"",str_extract( x[1], '".+"' ) )
x <- x[-1]
x <- x[-length(x)]
res <- c( res, gsub( "\\t", "", str_extract( x, "\\t[0-9a-zA-Z_]+" ) ) )
res
}
Code is somewhat sloppy, but it appears to work.
Try this sqlite table schema parser, I implemented the sqlite table parser for parsing the table definitions in PHP.
It returns the full definitions (unique, primary key, type, precision, not null, references, table constraints... etc)
https://github.com/maghead/sqlite-parser
Easiest way to get the column names of the most recently executed SELECT is to use the cursor's description property. A Python example:
print_me = "("
for description in cursor.description:
print_me += description[0] + ", "
print(print_me[0:-2] + ')')
# Example output: (inp, output, reason, cond_cnt, loop_likely)

Querying against LINQ to SQL relationships

Using LINQ to SQL
db.Products.Where(c => c.ID == 1).Skip(1).Take(1).ToList();
executes
SELECT [t1].[ID], [t1].[CategoryID], [t1].[Name], [t1].[Price], [t1].[Descripti
n], [t1].[IsFeatured], [t1].[IsActive]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID], [t0].[CategoryID], [t0].[Name
, [t0].[Price], [t0].[Description], [t0].[IsFeatured], [t0].[IsActive]) AS [ROW
NUMBER], [t0].[ID], [t0].[CategoryID], [t0].[Name], [t0].[Price], [t0].[Descrip
ion], [t0].[IsFeatured], [t0].[IsActive]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[ID] = #p0
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN #p1 + 1 AND #p1 + #p2
ORDER BY [t1].[ROW_NUMBER]
-- #p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- #p1: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- #p2: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
It's using ROW_NUMBER for pagination... good.
Now, I'm trying to use relationships generated by LINQ to SQL to paginate data. Using the query...
var cat = db.Categories.Where(c => c.ID == 1).SingleOrDefault();
cat.Products.Where(c => c.ID == 1).Skip(1).Take(1).ToList();
SELECT [t0].[ID], [t0].[Name]
FROM [dbo].[Categories] AS [t0]
WHERE [t0].[ID] = #p0
-- #p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1
SELECT [t0].[ID], [t0].[CategoryID], [t0].[Name], [t0].[Price], [t0].[Descriptio
n], [t0].[IsFeatured], [t0].[IsActive]
FROM [dbo].[Products] AS [t0]
WHERE [t0].[CategoryID] = #p0
-- #p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1
Now the use of ROW_NUMBER and pagination is gone... it's getting all Products where CategoryID = 1... why is it getting ALL rows?
I think its because the category is in memory. You are asking it, implicitly, to get the products of the category. This implicit request for data is for filled, and then in memory (where the category is at this point) the query is executed.
I'm thinking its equivalent to :
var cat = db.Categories.Where(c => c.ID == 1).SingleOrDefault();
var prods = db.Products.Where(c => c.ID == 1).ToList();
var r = prods.Where(p.CategoryID == cat.ID).Skip(1).Take(1);
Note the significance, what if cat changes in memory? The size of the collection could vary.
NOTE: Thanks for the headache :)
have you tried:
var cat = db.Categories.Where(c => c.ID == 1);
var prod = cat.Products.Where(c => c.ID == 1).Skip(1).Take(1).ToList();
You haven't assigned the output of your second LINQ query. So 'cat' is still the first query only.

Resources