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

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" = ? ))

Related

Select specific columns with repository in Entity Framework Core

I have a big table with a binary column for picture. I need to show contents of this table in a view and make it searchable. I have tried only selecting a subset of columns that are needed in this. However, the generated SQL always has all the columns of the table in the generated query.
public IQueryable<ApplicantDTO> GetApplicantQueryable()
{
return DataContext.Applicants
.Include(a => a.Nationality)
.Select(x => new ApplicantDTO
{
Id = x.Id,
BirthDate = x.BirthDate,
Gender = x.Gender,
FirstName = x.FirstName,
LastName = x.LastName,
OtherName = x.OtherName,
MobileNo = x.MobileNo,
Age = x.Age,
Nationality = x.Nationality.National,
Admitted = x.admitted,
Completed = x.Completed
})
.Where(a => a.Admitted == false && a.Completed == true)
.OrderBy(a => a.LastName)
.AsNoTracking();
}
But instead of just specifying the above rows, the generated SQL from profiler is
SELECT
[a].[Id], [a].[BirthDate], [a].[BirthPlace], [a].[CompleteDate],
[a].[Completed], [a].[ContentType], [a].[CreateDate],
[a].[Denomination], [a].[Disability], [a].[Email],
[a].[FirstName], [a].[Gender], [a].[HomeTown], [a].[LastName],
[a].[MarryStatus], [a].[MatureApp], [a].[MobileNo], [a].[NationalityID],
[a].[OtherName], [a].[Passport], [a].[Pin], [a].[PostalAddress],
[a].[Region], [a].[Religion], [a].[ResAddress], [a].[SerialNo],
[a].[Title], [a].[VoucherID], [a].[admitted], [a.Nationality].[National]
FROM
[Applicants] AS [a]
INNER JOIN
[Nationality] AS [a.Nationality] ON [a].[NationalityID] = [a.Nationality].[Id]
WHERE
([a].[admitted] = 0)
AND ([a].[Completed] = 1)
ORDER BY
[a].[LastName]
With all the underlying columns all included in the query.
I tried putting it in an anonymous type before casting it to the ApplicantDTO but still the same effect.
What's wrong?

Get data from a table after joining based on null value of joined table using LINQ

I have some tables like "Job" "AppliedJob" "JobOffer" "Contract" "Employeer"
Description: When employeer post job it is stored in "Job" table with his ID. If a freelancer apply to the job it is stored in "AppliedJob" table with his ID. Then Employeer sees the application and send offer to the freelancer and it is stored in "JobOffer" table. If freelancer accept the offer it is then stored in "Contract" table. At first in "Contract" ContractID, OfferID and StratDate are stored and CompletedDate is stored as null. When the contract is completed the CompletedDate field is modified with date.
Want: I want to return all jobs with no completed contract
I tried:
[HttpGet]
[Route("api/PrivateApi/GetEmployeerPostedJob/")]
public object GetEmployeerPostedJob(int id)
{
var data = (from j in db.Jobs
where j.EmployeerID == id
join apl in db.AppliedJobs
on j.JobID equals apl.JobID
join o in db.JobOffers
on apl.AppliedJobID equals o.AppliedJobID
join con in db.Contracts
on o.OfferID equals con.OfferID
where con.CompletedDate == null
select new
{
j.JobTitle,
j.JobID,
j.Budget,
j.Deadline,
j.Employeer,
j.JobDetails,
j.PublishDate,
j.ReqSkill,
j.NoOFFreelancer,
j.Preference,
Category1=j.Category,
totalAppliedFreelancer=(from aple in db.AppliedJobs where j.JobID ==aple.JobID select aple).Count(),
Category = (from gg in db.Categories where gg.CategoryID == j.Category select gg.CategoryName).FirstOrDefault()
}).ToList();
return data.AsEnumerable();
}
But it returns no jobs.
How can i get all jobs which are not completed yet(CompletedDate == null in Contract table)?
I want to show the employeer's posted jobs on his page but only those jobs that are not completed
The above (die to one to many relationships involved) can be paraphrased as
return all jobs with no completed contract
while the way you wrote the query, besides the possible data duplication, it answers the question
return all jobs with existing, but not completed contract
i.e. is missing the jobs w/o applied job, applied job w/o offer and offer w/o contract.
The correct query would be something like this:
from job in db.Jobs
where job.EmployeerID == id
join jobContract in (
from appliedJob in db.AppliedJobs
join offer in db.JobOffers on appliedJob.AppliedJobID equals offer.AppliedJobID
join contract in db.Contracts on offer.OfferID equals contract.OfferID
select new { appliedJob, offer, contract }
) on job.JobID equals jobContract.appliedJob.JobID into jobContracts
where !jobContracts.Any(jobContract => jobContract.contract.CompletedDate != null)
select ...
The query could further be simplified by using navigation properties, but since I don't see navigation properties between AppliedJob and JobOffer, I'm leaving that for you.
Update: Here is the same query with navigation properties (by simplified I meant no need for join operators):
from job in db.Jobs
let completedContracts =
from appliedJob in job.AppliedJobs
from offer in appliedJob.JobOffers
from contract in offer.Contracts
where contract.CompletedDate != null
select contract
where !completedContracts.Any()
select ...
This LINQ query doesn't work on live server (sql-2008) But works on my local VS 2013. Is there any mistake if my live database is empty at first time?
#Ivan Stoev
public object BrowseJobs()
{
var skills = db.Skills.ToDictionary(d => d.SkillID, n => n.SkillName);
var jobData = (from j in db.Jobs where j.Preference==2
//from cj in j.ClosedJobs.DefaultIfEmpty()
join cj in db.ClosedJobs.DefaultIfEmpty()
on j.JobID equals cj.JobID into closedJob
where !closedJob.Any()
join c in db.Categories on j.Category equals c.CategoryID
join jobContract in
(
from appliedJob in db.AppliedJobs.DefaultIfEmpty()
from offer in appliedJob.JobOffers.DefaultIfEmpty()
from contract in db.Contracts.DefaultIfEmpty()
select new { appliedJob, offer, contract }
).DefaultIfEmpty()
on j.JobID equals jobContract.appliedJob.JobID into jobContracts
where !jobContracts.Any(jobContract => jobContract.contract.CompletedDate != null)
select new
{
JobTitle = j.JobTitle,
JobID = j.JobID,
ReqSkillCommaSeperated = j.ReqSkill,
Category = c.CategoryName,
Budget=j.Budget,
Deadline=j.Deadline,
JobDetails=j.JobDetails,
PublishDate=j.PublishDate,
TotalApplied=(from ap in db.AppliedJobs where j.JobID == ap.JobID select ap.AppliedJobID).DefaultIfEmpty().Count()
}).AsEnumerable()
.Select(x => new
{
JobID = x.JobID,
JobTitle = x.JobTitle,
Category = x.Category,
Budget = x.Budget,
Deadline = x.Deadline,
JobDetails = x.JobDetails,
PublishDate = x.PublishDate,
SkillNames = GetSkillName(x.ReqSkillCommaSeperated, skills),
TotalApplied = (from ap in db.AppliedJobs where x.JobID == ap.JobID select ap.AppliedJobID).DefaultIfEmpty().Count()
}).ToList();
return jobData.AsEnumerable();
}

SQL Query Help - searching on multiple 'pairs' or data

I'm struggling to work out how to do a SQL query on a database that I have.
I have a view (which can be changed) which shows the relationships between the tables.
This creates a view as follows:
What I need to be able to do is search on one or more 'Attribute Pairs'
for example
I want to search for records with:
(
(AttributeName='FileExtension' AND AttributeValue='.pdf')
AND (AttributeName='AccountNumber' AND AttributeValue='ABB001'
)
As you can tell, this is not working as AttributeName cant be two things at once. I have this working with an OR filter, but I want it to find records that have all attribute pairs
SELECT
dbo.SiconDMSDocument.SiconDMSDocumentID,
dbo.SiconDMSAttribute.SiconDMSAttributeID,
dbo.SiconDMSAttribute.AttributeFriendlyName,
dbo.SiconDMSAttribute.AttributeName,
dbo.SiconDMSDocumentAttribute.AttributeValue,
dbo.SiconDMSAttribute.DataType,
dbo.SiconDMSDocumentType.SiconDMSDocumentTypeID,
dbo.SiconDMSDocumentType.DocumentTypeName,
dbo.SiconDMSDocumentType.DocumentTypeFriendlyName,
dbo.SiconDMSModule.SiconDMSModuleID,
dbo.SiconDMSModule.ModuleName,
dbo.SiconDMSModule.ModuleFriendlyName,
dbo.SiconDMSDocument.SiconDMSDocumentTypeModuleID
FROM dbo.SiconDMSDocument
INNER JOIN dbo.SiconDMSDocumentAttribute ON dbo.SiconDMSDocument.SiconDMSDocumentID = dbo.SiconDMSDocumentAttribute.SiconDMSDocumentID
INNER JOIN dbo.SiconDMSAttribute ON dbo.SiconDMSDocumentAttribute.SiconDMSAttributeID = dbo.SiconDMSAttribute.SiconDMSAttributeID
AND
(
(dbo.SiconDMSAttribute.AttributeName = 'Reference' AND dbo.SiconDMSDocumentAttribute.AttributeValue='12345')
OR (dbo.SiconDMSAttribute.AttributeName = 'AccountNumber' AND dbo.SiconDMSDocumentAttribute.AttributeValue='ABB001')
)
INNER JOIN dbo.SiconDMSDocumentTypeModule ON dbo.SiconDMSDocument.SiconDMSDocumentTypeModuleID = dbo.SiconDMSDocumentTypeModule.SiconDMSDocumentTypeModuleID
INNER JOIN dbo.SiconDMSDocumentType ON dbo.SiconDMSDocumentTypeModule.SiconDMSDocumentTypeID = dbo.SiconDMSDocumentType.SiconDMSDocumentTypeID
INNER JOIN dbo.SiconDMSModule ON dbo.SiconDMSDocumentTypeModule.SiconDMSModuleID = dbo.SiconDMSModule.SiconDMSModuleID
WHERE
(dbo.SiconDMSDocument.Deleted = 0)
AND (dbo.SiconDMSDocumentAttribute.Deleted = 0)
AND (dbo.SiconDMSAttribute.Deleted = 0)
AND (dbo.SiconDMSDocumentType.Deleted = 0)
AND (dbo.SiconDMSDocumentTypeModule.Deleted = 0)
AND (dbo.SiconDMSModule.Deleted = 0)
Are there any SQL functions that will allow me to do something like this?
I'm not sure what your complicated query has to do with the question of searching for attribute pairs.
Assuming you want the document ids that have both attributes:
select SiconDMSDocumentID
from yourview y
where (AttributeName = 'FileExtension' AND AttributeValue = '.pdf') or
(AttributeName = 'AccountNumber' AND AttributeValue = 'ABB001'
group by SiconDMSDocumentID
having count(*) = 2;
Or, if the attributes could have multiple values:
having count(distinct AttributeName) = 2

syntax to query another table using relationship in ORM?

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)

GQL SELECT Sorting

is there any easier way to select & sort by weight ?
fetchCount = 1000
date1 = datetime.datetime.utcnow().date()
entries = GqlQuery("SELECT * FROM Entry WHERE category = :category and date >= :datetime ORDER BY date, weight DESC", category = category, datetime = date1).fetch(fetchCount)
if entries is not None:
# Sort entries ( lazy way for now ).
sort = True
while sort:
sort = False
for i in range(0, len(entries)-1):
if entries[i].weight < entries[i + 1].weight:
e = entries[i + 1]
entries[i + 1] = entries[i]
entries[i] = e
sort = True
solved by:
entries = GqlQuery("SELECT * FROM Entry WHERE category = :category and date > :datetime ORDER BY date, weight DESC", category = category, datetime = date1).fetch(fetchCount)
entries = sorted(entries, key=lambda x: x.weight, reverse=True)
since there is no other way atm....
It's a limitation of the datastore that if you use an inequality filter (e.g. date >= :datetime) that must also be your first ordering key. Also, you can only have inequalities on one property per query. So, in your case you have no choice but sorting them in memory. The sorted() call in the other answer is perfect.

Resources