I have some problem with my database query. I need to set max results, but when i'm doing that i don't have result what i expected. (eg. when i have 2 "hashtags" decreases by one)
Here is code:
$r = $this->createQueryBuilder("q")
->select("q AS image, sb, hs")
->addSelect("c, SUM(CASE WHEN (c.likeCount!=false) THEN c.likeCount ELSE 0 END) AS likes")
->addSelect("cm, COUNT(cm) AS comments")
->addSelect("u, SUM(CASE WHEN (c.user=:user) THEN c.likeCount ELSE 0 END) AS userLiked")
->leftJoin("q.siteBox","sb")
->leftJoin("q.imageLikes","c")
->leftJoin("q.hashtags","hs")
->leftJoin("q.comments","cm")
->setMaxResults(4)
->leftJoin("c.user","u")
->setParameter("user",$user)
->groupBy("hs.id,q.id")
->orderBy("q.date","DESC")
;
Sorry for my bad english, but i wthink everybody will understand.
Related
I have a data.frame named as data6 on which i want to perform pivot.
i have tried sqldf but after checking thoroughly still i couldn't find why this error is coming
"Error in result_create(conn#ptr, statement) : near "(": syntax error"
sql statement: "Select * From (Select * From data6) PIVOT(sum([Qty]) FOR [GRNUOM] in ([con2],[con3],[con4],[Con15],[Con2],[Con3],[Con4])"
Using recast/dcast function it can be done but as a new user i don't know how to do it. even i don't know what is difference between recast & dcast.
I know it's a lot of questions but if anyone help me out on this
The sqldf package by default uses SQLite as the underlying database, and therefore the PIVOT syntax you are using won't work. While you might be able to change the underlying database to SQL Server, you could also just use an ANSI standard pivot query:
sql <- "SELECT \"Style Name\",
SUM(CASE WHEN GRNUOM = 'con2' THEN Qty ELSE 0 END) AS con2,
SUM(CASE WHEN GRNUOM = 'con3' THEN Qty ELSE 0 END) AS con3,
SUM(CASE WHEN GRNUOM = 'con4' THEN Qty ELSE 0 END) AS con4,
SUM(CASE WHEN GRNUOM = 'Con15' THEN Qty ELSE 0 END) AS Con15,
SUM(CASE WHEN GRNUOM = 'Con2' THEN Qty ELSE 0 END) AS Con2,
SUM(CASE WHEN GRNUOM = 'Con3' THEN Qty ELSE 0 END) AS Con3,
SUM(CASE WHEN GRNUOM = 'Con4' THEN Qty ELSE 0 END) AS Con4
FROM data6
GROUP BY \"Style Name\""
result <- sqldf(sql)
I am not certain if con2 and Con2 would actually be recognized as separate column names. You might have to put all column names in double quotes to make the above query work the way you expect.
Found related type solutions, but nothing to match my need;
I want to update an existing table record (fields pu_cnt, pu_ot, pu_ltc etc.) with the result from the query (pu_cnt, pu_ot, pu_ltc etc.) etc.
Here's my query:
SELECT
COUNT(CASE WHEN vuWO_CHC_ALL.status IN('C','D','H','F') THEN 1 END) AS
pu_cnt,
COUNT(CASE WHEN LEFT(vuWO_CHC_ALL.actpu_delay_code,1) LIKE '' THEN 1 END) AS
pu_ot,
COUNT(CASE WHEN LEFT(vuWO_CHC_ALL.actpu_delay_code,1) LIKE 'C' THEN 1 END)
AS pu_ltc,
COUNT(CASE WHEN LEFT(vuWO_CHC_ALL.actpu_delay_code,1) LIKE 'U' THEN 1 END)
AS pu_ltu,
COUNT(CASE WHEN vuWO_CHC_ALL.status IN('D','H','F') THEN 1 END) AS del_cnt,
COUNT(CASE WHEN LEFT(vuWO_CHC_ALL.actdel_delay_code,1) LIKE '' THEN 1 END) AS
del_ot,
COUNT(CASE WHEN LEFT(vuWO_CHC_ALL.actdel_delay_code,1) LIKE 'C' THEN 1 END)
AS del_ltc,
COUNT(CASE WHEN LEFT(vuWO_CHC_ALL.actdel_delay_code,1) LIKE 'U' THEN 1 END)
AS del_ltu
FROM vuWO_CHC_ALL WHERE
RTRIM(vuWO_CHC_ALL.SHIPPER) LIKE #pVendor AND
RTRIM(vuWO_CHC_ALL.ORIG) LIKE #pOrigin AND
RTRIM(vuWO_CHC_ALL.Dest) LIKE #pDestin
..
Figured it out using #variables.
Trying to optimize a query, which has multiple counts for objects in subordinate table (used aliases in SQLAlchemy). In Witch Academia terms, something like this:
SELECT
exam.id AS exam_id,
exam.name AS exam_name,
count(tried_witch.id) AS tried,
count(passed_witch.id) AS passed,
count(failed_witch.id) AS failed
FROM exam
LEFT OUTER JOIN witch AS tried_witch
ON tried_witch.exam_id = exam.id AND
tried_witch.is_failed = 0 AND
tried_witch.status != "passed"
LEFT OUTER JOIN witch AS passed_witch
ON passed_witch.exam_id = exam.id AND
passed_witch.is_failed = 0 AND
passed_witch.status = "passed"
LEFT OUTER JOIN witch AS failed_witch
ON failed_witch.exam_id = exam.id AND
failed_witch.is_failed = 1
GROUP BY exam.id, exam.name
ORDER BY tried ASC
LIMIT 20
Number of witches can be large (hundreds of thousands), number of exams is lower (hundreds), so the above query is quite slow. In a lot of similar questions I've found answers, which propose the above, but I feel like a totally different approach is needed here. I am stuck at coming up with alternative. NB, there is a need to order by calculated counts. It is also important to have zeros as counts, of course, where due. (do not pay attention to a somewhat funny model: witches can easily clone themselves to go to multiple exams, thus per exam identity)
With one EXISTS subquery, which is not reflected in the above and does not influence the ouotcome, the situation is:
# Query_time: 1.135747 Lock_time: 0.000209 Rows_sent: 20 Rows_examined: 98174
# Rows_affected: 0
# Full_scan: Yes Full_join: No Tmp_table: Yes Tmp_table_on_disk: Yes
# Filesort: Yes Filesort_on_disk: No Merge_passes: 0 Priority_queue: No
Updated query, which is still quite slow:
SELECT
exam.id AS exam_id,
exam.name AS exam_name,
count(CASE WHEN (witch.status != "passed" AND witch.is_failed = 0)
THEN witch.id
ELSE NULL END) AS tried,
count(CASE WHEN (witch.status = "passed" AND witch.is_failed = 0)
THEN witch.id
ELSE NULL END) AS passed,
count(CASE WHEN (witch.is_failed = 1)
THEN witch.id
ELSE NULL END) AS failed
FROM exam
LEFT OUTER JOIN witch ON witch.exam_id = exam.id
GROUP BY exam.id, exam.name
ORDER BY tried ASC
LIMIT 20
Indexing is the key to get performance of the query.
I do not know MariaDB at all, so not sure what the possibilities are. But if it is anything like Microsoft SQL Server, then here is what I would try:
Create ONE composite index covering ALL the required columns: witch_id, status and is_failed. If the query uses that index, that should be it. Here the order of the included columns might be very important. Then profile the query in order to understand if the index is used. See Optimization and Indexes documentation page.
Consider Generated (Virtual and Persistent) Columns.
It looks like all the information for classification of the witch into tried, passed or failed bucket is contained in the row for witch. Therefore, you can basically create those virtual columns on the database table directly and use PERSISTENT option. This option allows creating index on it. Then you can create an index specifically for this query containing witch_id and three virtual columns: tried, passed and failed. Make sure you query uses it, and that should be pretty good. The query will then look very simple:
SELECT exam.id,
exam.name,
sum(witch.tried) AS tried,
sum(witch.passed) AS passed,
sum(witch.failed) AS failed
FROM exam
INNER JOIN witch ON exam.id = witch.exam_id
GROUP BY exam.id,
exam.name
ORDER BY sum(witch.tried)
LIMIT 20
Although query simple comparisons and AND/OR clauses, you are basically offloading the calculation of the 3 statuses to the database during INSERT/UPDATE. Then during SELECT you query should be much faster.
Your example does not specify any result filtering (WHERE clause), but if you have one, it might also have an impact on the way one optimises indices for query performance.
Original answer: Below is the originally proposed change to the query.
Here i assume that indexing part of the optimisation has been already done.
Could you try with SUM instead of COUNT?
SELECT exam.id,
exam.name,
sum(CASE
WHEN (witch.is_failed = 0
AND witch.status != 'passed') THEN 1
ELSE 0
END) AS tried,
sum(CASE
WHEN (witch.is_failed = 0
AND witch.status = 'passed') THEN 1
ELSE 0
END) AS passed,
sum(CASE
WHEN (witch.is_failed = 1) THEN 1
ELSE 0
END) AS failed
FROM exam
INNER JOIN witch ON exam.id = witch.exam_id
GROUP BY exam.id,
exam.name
ORDER BY sum(CASE
WHEN (witch.is_failed = 0
AND witch.status != 'passed') THEN 1
ELSE 0
END)
LIMIT 20
The rest:
Given you have specified sqlalchemy in your answer, here is the sqlalchemy code, which i used to model and generate the query:
# model
class Exam(Base):
id = Column(Integer, primary_key=True)
name = Column(String)
class Witch(Base):
id = Column(Integer, primary_key=True)
exam_id = Column(Integer, ForeignKey('exam.id'))
is_failed = Column(Integer)
status = Column(String)
exam = relationship(Exam, backref='witches')
# computed fields
#hybrid_property
def tried(self):
return self.is_failed == 0 and self.status != 'passed'
#hybrid_property
def passed(self):
return self.is_failed == 0 and self.status == 'passed'
#hybrid_property
def failed(self):
return self.is_failed == 1
# computed fields: expression
#tried.expression
def _tried_expression(cls):
return case([(and_(
cls.is_failed == 0,
cls.status != 'passed',
), 1)], else_=0)
#passed.expression
def _passed_expression(cls):
return case([(and_(
cls.status == 'passed',
cls.is_failed == 0,
), 1)], else_=0)
#failed.expression
def _failed_expression(cls):
return case([(cls.is_failed == 1, 1)], else_=0)
and:
# query
q = (
session.query(
Exam.id, Exam.name,
func.sum(Witch.tried).label("tried"),
func.sum(Witch.passed).label("passed"),
func.sum(Witch.failed).label("failed"),
)
.join(Witch)
.group_by(Exam.id, Exam.name)
.order_by(func.sum(Witch.tried))
.limit(20)
)
I have an sql-select (or insert) which uses the same two parameters several times.
Is there a way to avoid using multiple the same parameter for every "?,?,?,?,..." in the list ?
cursor.execute(statement, list)
I could think of two named parameters but without the possibility of code-injection.
In the example below every left "?" resp. right "?" is the same string. I used the seven counts in one statement in order to get one result.
select count(case (aart like "1%") and (adatum between ? and ?) when 1 then 1 else null end) as AufExt,
count(case (aart like "1%E") and (adatum between ? and ?) when 1 then 1 else null end) as AufExtE,
count(case (aart like "1%K") and (adatum between ? and ?) when 1 then 1 else null end) as AufExtK,
count(case (aart like "2S%") and (adatum between ? and ?) when 1 then 1 else null end) as AufInt,
count(case (eart like "3%") and (edatum between ? and ?) when 1 then 1 else null end) as EntExt,
count(case (eart like "3%K") and (edatum between ? and ?) when 1 then 1 else null end) as EntExtK,
count(case (eart like "2S%") and (edatum between ? and ?) when 1 then 1 else null end) as EntInt
from tabelle
Related question to this problem: It looks as if no index is used in "case". Correct?
The documentation says:
? A question mark that is not followed by a number creates a parameter with a number one greater than the largest parameter number already assigned. [...]
?NNN A question mark followed by a number NNN holds a spot for the NNN-th parameter. [...]
:AAAA A colon followed by an identifier name holds a spot for a named parameter with the name :AAAA. Named parameters are also numbered. [...] To avoid confusion, it is best to avoid mixing named and numbered parameters.
you can also add with clause like this:
with
parms as (select ? as parm1, ? as parm2)
select count(case (aart like "1%") and (adatum between parms.parm1 and parms.parm2) when 1 then 1 else null end) as AufExt
...
I've been writing a cypher query to count all nodes with a label, property, or relationship that contain the criteria typed in by the user. When I do this query, I want a count of all the nodes with unique label names (which I've accomplished). I also want a count of all the nodes that contain specific relationships.
This is the part of the query that returns a count of all the nodes with the labels: Fruit, Lesson, Tech, and TestData. I left out the WHERE clause because it's pretty long.
match (n)
return
sum(CASE when any(l IN labels(n) WHERE l='Fruit') THEN 1 ELSE 0 END) AS Fruit,
sum(CASE when any(l IN labels(n) WHERE l='Lesson') THEN 1 ELSE 0 END) AS Lesson,
sum(CASE when any(l IN labels(n) WHERE l='Tech') THEN 1 ELSE 0 END) AS Tech,
sum(CASE when any(l IN labels(n) WHERE l='TestData') THEN 1 ELSE 0 END) AS TestData
It returns
Fruit Lesson Tech TestData
1000 20 100 50
However, I'd also like to count the number of nodes that had specific relationships (I know the names ahead of time) like "KNOWS", "IS_A", and "DESTINATION." For instance, if a user was searching for the word "knows" and the resulting nodes had a relationship called "knows," then I would count that node. Afterwards, my query would report that I had found 20 nodes that were connected via the "knows" relationship.
I'd like to do this without excluding any of my result nodes. Notice I didn't include any relationships in the match clause. I still want to include nodes that don't have a relationship (I don't care about counting that).
Does anyone know how to do this? Can it be done?
I'm looking for something similar to this:
match (n)
return
sum(CASE when any(r IN rels(n) WHERE r='KNOWS') THEN 1 ELSE 0 END) AS KNOWS,
sum(CASE when any(r IN rels(n) WHERE r='IS_A') THEN 1 ELSE 0 END) AS IS_A,
sum(CASE when any(r IN rels(n) WHERE r='DESTINATION') THEN 1 ELSE 0 END) AS DESTINATION,
Not sure if I catch what you mean with "count the nodes that matched specific relationships" and "without excluding any of my result nodes". Do you mean to count cases where a node has at least one relationship in any direction of each type (and if for instance the node has two or five such relationships it still counts as one), as opposed to counting the relationships? Or do you mean that you want a sub-query that works in combination with the previous query counting labels? Does this do what you want?
MATCH (n)
OPTIONAL MATCH (n)-[r]-()
WITH n, collect(r) as rs
SUM(CASE WHEN ANY(l IN labels(n) WHERE l='Fruit') THEN 1 ELSE 0 END) AS Fruit,
SUM(CASE WHEN ANY(l IN labels(n) WHERE l='Lesson') THEN 1 ELSE 0 END) AS Lesson,
SUM(CASE WHEN ANY(l IN labels(n) WHERE l='Tech') THEN 1 ELSE 0 END) AS Tech,
SUM(CASE WHEN ANY(l IN labels(n) WHERE l='TestData') THEN 1 ELSE 0 END) AS TestData,
SUM(CASE WHEN ANY(r IN rs WHERE type(r)='KNOWS') THEN 1 ELSE 0 END) AS KNOWS,
SUM(CASE WHEN ANY(r IN rs WHERE type(r)='IS_A') THEN 1 ELSE 0 END) AS IS_A,
SUM(CASE WHEN ANY(r IN rs WHERE type(r)='DESTINATION') THEN 1 ELSE 0 END) AS DESTINATION
Something that you could try, that may be an improvement, would be to match each thing you want to count explicitly, count it, and carry the count with WITH until you return. This has particular benefits if there are many things in your database that you are not counting, which on the query above will be matched and evaluated anyway. So you could experiment with something like
MATCH (n:Fruit)
WITH count(n) as Fruit
MATCH (n:'Lesson')
WITH Fruit, count(n) as Lesson
MATCH (n:'Tech')
WITH Fruit, Lesson, count(n) as Tech
MATCH (n:TestData)
WITH Fruit, Lesson, Tech, count(n) as TestData
MATCH (n)-[:KNOWS]-()
WITH Fruit, Lesson, Tech, TestData, count(n) as KNOWS
MATCH (n)-[:IS_A]-()
WITH Fruit, Lesson, Tech, TestData, KNOWS, count(n) as IS_A
MATCH (n)-[:DESTINATION]-()
RETURN Fruit, Lesson, Tech, TestData, KNOWS, IS_A, count(n) as DESTINATION
I don't know how much of a difference it will make on your data, but it's better as far as possible to use narrow or specific patterns rather than to use a broad pattern and then filter. It may be worth profiling the two queries and compare.