syntax to query another table using relationship in ORM? - database

The model is like this(in SQLAlchemy):
Class Cell(Base):
__tablename__ = "cell"
id = Column(Integer)
name = Column(String)
Class Sample(Base):
__tablename__ = "cell"
id = Column(Integer)
factor_id = Column(Integer, ForeignKey("cell.id"))
cell = relationship(Cell, backref = 'sample', order_by = "Cell.id")
When I execute the query like this:
DBSession.query(Sample).filter(Sample.cell.name == "a_string")
It throws an exception like this:
File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/attributes.py", line 139, in __getattr__
key)
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute 'name'
It seems that the cell field in Sample class doesn't have a field called name. Then how can I query Cell.name in Sample class with cell field? Does anyone have ideas about this?
Thanks!

There are various ways to achieve that:
1. use join(...) - I would opt for this one in your case
qry = session.query(Sample).join(Cell).filter(Cell.name == "a_string")
>> SELECT sample.id AS sample_id, sample.factor_id AS sample_factor_id
>> FROM sample JOIN cell ON cell.id = sample.factor_id
>> WHERE cell.name = :name_1
2. use any/has(...) - this will use a sub-query
qry = session.query(Sample).filter(Sample.cell.has(Cell.name == "a_string"))
>> SELECT sample.id AS sample_id, sample.factor_id AS sample_factor_id
>> FROM sample
>> WHERE EXISTS (SELECT 1
>> FROM cell
>> WHERE cell.id = sample.factor_id AND cell.name = :name_1)

Related

peewee ORM limits query, how do I remove the limit?

I have this query:
SELECT * FROM "transaction"
WHERE type = {transaction_type} AND
from_member_id IN (SELECT member_id FROM dao_member WHERE org_id = "{org}") AND
to_member_id IN (SELECT member_id FROM dao_member WHERE org_id = "{org}")
Which I have written in peewee like this:
members = ORG_Member.select(ORG_Member.member).where(ORG_Member.org_id == org)
transactions = Transaction.select().where(
Transaction.type == transaction_type).where(
Transaction.from_member.in_(members)).where(
Transaction.to_member.in_(members)).sql()
The SQL shown is then;
SELECT * FROM "transaction" AS "t1"
WHERE ((("t1"."type" = ?)
AND ("t1"."from_member_id" IN
(SELECT "t2"."member_id" FROM "org_member" AS "t2" WHERE ("t2"."org_id" = ?) LIMIT ?)))
AND ("t1"."to_member_id" IN
(SELECT "t2"."member_id" FROM "org_member" AS "t2" WHERE ("t2"."org_id" = ?) LIMIT ?))),
[1, 'lala', 1, 'baba', 1])
Notice the limit! Where did this limit come from? I've tried setting limit explicitly to None, no luck.
I don't observe that. Probably you have omitted some important details.
from peewee import *
db = SqliteDatabase(':memory:')
class Member(Model):
org_id = IntegerField(default=0)
class Meta:
database = db
class Transaction(Model):
from_member = ForeignKeyField(Member, backref='from_tx')
to_member = ForeignKeyField(Member, backref='to_tx')
type = TextField()
class Meta:
database = db
members = Member.select().where(Member.org_id == 0)
txns = (Transaction.select()
.where(Transaction.type == 'tx-type')
.where(Transaction.from_member.in_(members))
.where(Transaction.to_member.in_(members)))
print(txns.sql())
This results in:
SELECT "t1"."id", ...
FROM "transaction" AS "t1"
WHERE "t1"."type" = ? AND
"t1"."from_member_id" IN (SELECT "t2"."id"
FROM "member" AS "t2"
WHERE ( "t2"."org_id" = ? )) AND
"t1"."to_member_id" IN (SELECT "t2"."id"
FROM "member" AS "t2"
WHERE ( "t2"."org_id" = ? ))

Can Any one help me to convert this sql query into linq

I need to convert this SQL Query to Link :
"Select * FROM [Register]
where RegisterId IN (SELECT MyId
FROM Friends
WHERE FriendId='" + Session["CurrentProfileId"] + "'
AND Status=1
UNION
SELECT FriendId
FROM Friends
WHERE MyId='" + Session["CurrentProfileId"] + "'
AND Status=1) ";
It may be look like this??? but this is incorrect and having errors
(from u in db.Register
where RegisterId).Contains
(from f in db.Freinds
where f.MyId == Id && m.Status == 1
select new { m.MyId })
.Union(from m in db.Freinds
where f.FreindId == Id && m.Status == 1
select new { m.CreateDate } ));
You have a few problems with the linq above and here are a few:
In the query in the Union you select the CreateDate whereas in the top on you select the MyId. I assume you meant to select FreindId.
In these 2 queries you create an anonymous class instance with the field but then compare it to the RegisterId which is probably a guid/string/int - but for sure not of the type you just created.
You are using the Contains method wrong. Linq syntax can be similar to sql but it is not the same. Check here for Contains
The correct Linq way of doing it is:
var idsCollection = ((from f in db.Freinds
where f.StatusId == 1 && f.MyId == Id
select f.MyId)
.Union(from m in db.Friends
where m.StatusId == 1 && f.FreindId == Id
select m.FriendId)).ToList();
var result = (from u in db.Register
where idsCollection.Contains(u.RegisterId)
select u).ToList();
Notice that the .ToList() is not a must and is here just to ease in debugging. For more information about this .ToList() and Linq in general check MSDN

power query excel table mssql returns invalid column name

Here is my Customer Parameters table
let
Source = Excel.CurrentWorkbook(){[Name="Customer"]}[Content],
Customer1 = Source{0}[Customer]
in
Customer1
And my Query
let
Customer = Excel.CurrentWorkbook(){[Name="Customer"]}[Content],
Customer_Name = Customer{0}[Customer],
Source = Sql.Database("SERVER", "DATABASE", [Query="SELECT i.PriorityType as 'PRIORITY','COUNT' = COUNT(i.IncidentID)#(lf)FROM ININ_ISupport_S_Incident_Search2 (NULL) i#(lf)WHERE IncidentType IN ('Customer Support','Managed Services')#(lf)AND Organization = Customer_Name#(lf)AND IsResolved = 0#(lf)AND Active = 1#(lf)AND StateType = 'Open'#(lf)GROUP BY i.PriorityType#(lf)ORDER BY CASE#(lf) WHEN i.PriorityType = 'Code Red' THEN 1#(lf) WHEN i.PriorityType = 'Code Red RCA' THEN 2#(lf) WHEN i.PriorityType = 'High' THEN 3#(lf) WHEN i.PriorityType = 'Medium' THEN 4#(lf) WHEN i.PriorityType = 'Low' THEN 5#(lf)END ASC"])
in
Source
I am setting Organization = Customer_Name but I keep getting the following
Message=Invalid column name 'Customer_Name'
Is there a way to accomplish this
Customer_Name is not a column in your SQL table, so it fails with that message. If you want to use Customer_Name in the query, it needs to be added to the string. This is done using the & operator. In your case, you would do something like
"...AND Organization = '" & Customer_Name & "'#(lf)AND IsResolved...
That will cause problems if the customer name has a quote in it (like O'Neill), so you could do
"...AND Organization = '" & Text.Replace(Customer_Name, "'", "''") & "'#(lf)AND IsResolved...
to try and escape quotes.
Escaping quotes is not always sufficient, so if you're running this query on a database where outsiders can create customers you should avoid using the above method. If you filter the column by Customer_Name (through Table.SelectRows(tableName, each [Organization] = Customer_Name)), you should get the same result without any security concerns.

How to use IN Clause for list of strings or GUID's in Dapper

I am trying to write a dapper query for IN clause, but it's not working throwing casting error saying "Conversion failed when converting the nvarchar value 'A8B08B50-2930-42DC-9DAA-776AC7810A0A' to data type int." . In below query fleetAsset is Guid converted into string.
public IQueryable<MarketTransaction> GetMarketTransactions(int fleetId, int userId, int rowCount)
{
//Original EF queries which I am trying to convert to Dapper
//var fleetAsset = (from logicalFleetNode in _context.LogicalFleetNodes
// where logicalFleetNode.LogicalFleetId == fleetId
// select logicalFleetNode.AssetID).ToList();
////This query fetches guid of assetprofiles for which user having permissions based on the assets user looking onto fleet
//var assetProfileIds = (from ap in _context.AssetProfileJoinAccounts
// where fleetAsset.Contains(ap.AssetProfile.AssetID) && ap.AccountId == userId
// select ap.AssetProfileId).ToList();
var fleetAsset = _context.Database.Connection.Query<string>("SELECT CONVERT(varchar(36),AssetID) from LogicalFleetNodes Where LogicalFleetId=#Fleetid",
new { fleetId }).AsEnumerable();
//This query fetches guid of assetprofiles for which user having permissions based on the assets user looking onto fleet
var sql = String.Format("SELECT TOP(#RowCount) AssetProfileId FROM [AssetProfileJoinAccounts] AS APJA WHERE ( EXISTS (SELECT " +
"1 AS [C1] FROM [dbo].[LogicalFleetNodes] AS LFN " +
"INNER JOIN [dbo].[AssetProfile] AS AP ON [LFN].[AssetID] = [AP].[AssetID]" +
" WHERE ([APJA].[AssetProfileId] = [AP].[ID]) " +
" AND ([APJA].[AccountId] = #AccountId AND LogicalFleetId IN #FleetId)))");
var assetProfileIds = _context.Database.Connection.Query<Guid>(sql, new { AccountId = userId, FleetId = fleetAsset, RowCount=rowCount });
Dapper performs expansion, so if the data types match, you should just need to do:
LogicalFleetId IN #FleetId
(note no parentheses)
Passing in a FleetId (typically via an anonymous type like in the question) that is an obvious array or list or similar.
If it isn't working when you remove the parentheses, then there are two questions to ask:
what is the column type of LocalFleetId?
what is the declared type of the local variable fleetAsset (that you are passing in as FleetId)?
Update: test case showing it working fine:
public void GuidIn_SO_24177902()
{
// invent and populate
Guid a = Guid.NewGuid(), b = Guid.NewGuid(),
c = Guid.NewGuid(), d = Guid.NewGuid();
connection.Execute("create table #foo (i int, g uniqueidentifier)");
connection.Execute("insert #foo(i,g) values(#i,#g)",
new[] { new { i = 1, g = a }, new { i = 2, g = b },
new { i = 3, g = c },new { i = 4, g = d }});
// check that rows 2&3 yield guids b&c
var guids = connection.Query<Guid>("select g from #foo where i in (2,3)")
.ToArray();
guids.Length.Equals(2);
guids.Contains(a).Equals(false);
guids.Contains(b).Equals(true);
guids.Contains(c).Equals(true);
guids.Contains(d).Equals(false);
// in query on the guids
var rows = connection.Query(
"select * from #foo where g in #guids order by i", new { guids })
.Select(row => new { i = (int)row.i, g = (Guid)row.g }).ToArray();
rows.Length.Equals(2);
rows[0].i.Equals(2);
rows[0].g.Equals(b);
rows[1].i.Equals(3);
rows[1].g.Equals(c);
}

Django Field Choices

Given below is my Model definition and I have added this module part of the Admin. I'm trying to create new row and while selecting value '3' or any other value for Duration field(listed as select fields), I get the following error.- "Value 3 is not a valid choice".
Please provide your inputs.
Model Definition
NO_OF_HRS = (
('1','One'),
('2','Two'),
('3','Three'),
('4','Four'),
('5','Five'),
('6','Six'),
('7','Seven'),
('8','Eight'),
('9','Nine'),
('10','Ten'),
('11','Eleven'),
('12','Twelve'),
)
YR_MONTH = (
("Y", "Year"),
("M", "Month"),
)
POS_STATUS = (
("A", "Active"),
("C", "Closed"),
)
datecreated = models.DateTimeField()
volposition = models.CharField(max_length=300)
roledesc = models.CharField(max_length=5000)
noofhours = models.IntegerField(blank = True,null = True)
Qualreqt = models.CharField(max_length=8000)
Duration = models.IntegerField(choices=NO_OF_HRS,blank = True,null = True)
Durationyrmon = models.CharField(choices=YR_MONTH,max_length=10)
posstatus = models.CharField(choices=POS_STATUS,max_length=1)
teamrelation = models.CharField(max_length=50)
When you use choices, the first value of the tuple is the value that will be stored in the database and the second value is the value that will be shown in the admin.
In NO_OF_HRS the values are strings (for example '1', '2') but it is a models.IntegerField so the values should be integers. That's why you're now getting an error.
Opened a ticket on django with fix and dirty fix:
https://code.djangoproject.com/ticket/24897

Resources