CriteriaQuery equivalent for conditional sum query in MySQL? - spring

In MySQL, I can use the following conditional sum query to count the number of rows, grouped by specific conditions:
SELECT SUM(synced=true) AS sum_a, SUM(synced=false) AS sum_b from test_table where name = "xyz";
I am trying to translate this into an equivalent CriteriaQuery, however, am not able to do so. How would the CriteriaQuery equivalent look for this?
So far, the closest I have reached is using a multiselect function with selectCase expressions as follows:
criteriaQuery.multiselect(
criteriaBuilder.sum(
criteriaBuilder.<Number>selectCase().when(/* conditions for sum_a */), 1
).otherwise(0)
).alias("sum_a"),
criteriaBuilder.sum(
criteriaBuilder.<Number>selectCase().when(/* conditions for sum_b */), 1
).otherwise(0)
).alias("sum_b"),
The above approach, however, is different from the SQL query mentioned at the beginning, even though it returns the correct values.

The query you posted looks correct. That's as good as it gets. You can't reproduce the exact same SQL with HQL or the JPA Criteria API. In fact, the syntax of the SQL query is MySQL specific and only works because MySQL doesn't have native boolean support, but models this as integer 1 and 0. The SQL standard way to model this is to use the fact that aggregate functions are null rejecting and use a case when expression that produces null if your condition is not fulfilled.
criteriaQuery.multiselect(
criteriaBuilder.sum(
criteriaBuilder.<Integer>selectCase().when(/* conditions for sum_a */), 1
).otherwise(criteriaBuilder.nullLiteral(Integer.class))
).alias("sum_a"),
criteriaBuilder.sum(
criteriaBuilder.<Integer>selectCase().when(/* conditions for sum_b */), 1
).otherwise(criteriaBuilder.nullLiteral(Integer.class))
).alias("sum_b"),

Related

Power BI DAX measure: Count occurences of a value in a column considering the filter context of the visual

I want to count the occurrences of values in a column. In my case the value I want to count is TRUE().
Lets say my table is called Table and has two columns:
boolean value
TRUE() A
FALSE() B
TRUE() A
TRUE() B
All solutions I found so far are like this:
count_true = COUNTROWS(FILTER(Table, Table[boolean] = TRUE()))
The problem is that I still want the visual (card), that displays the measure, to consider the filters (coming from the slicers) to reduce the table. So if I have a slicer that is set to value = A, the card with the count_true measure should show 2 and not 3.
As far as I understand the FILTER function always overwrites the visuals filter context.
To further explain my intent: At an earlier point the TRUE/FALSE column had the values 1/0 and I could achieve my goal by just using the SUM function that does not specify a filter context and just acts within the visuals filter context.
I think the DAX you gave should work as long as it's a measure, not a calculated column. (Calculated columns cannot read filter context from the report.)
When evaluating the measure,
count_true = COUNTROWS ( FILTER ( Table, Table[boolean] = TRUE() ) )
the first argument inside FILTER is not necessarily the full table but that table already filtered by the local filter context (including report/page/visual filters along with slicer selections and local context from e.g. rows/column a matrix visual).
So if you select Value = "A" via slicer, then the table in FILTER is already filtered to only include "A" values.
I do not know for sure if this will fix your problem but it is more efficient dax in my opinion:
count_true = CALCULATE(COUNTROWS(Table), Table[boolean])
If you still have the issue after changing your measure to use this format, you may have an underlying issue with the model. There is also the function KEEPFILTERS that may apply here but I think using KEEPFILTERS is overcomplicating your case.

Sort query by column

I am trying to make a query on Google Sheets and sort the results according to the highest values on column C. The range I am doing the query on is $A$6:$O.
I have tried to do it like this:
=SORT(QUERY(($A$6:$O), "Select A, B, C, D,E,F,G,H,I group by C"))
However, I am always getting an error saying
#VALUE: Unable to parse query string for Function QUERY parameter 2: CANNOT_GROUP_WITHOUT_AGG
Do you have any idea about how I can make this work?
Use the ORDER BY clause in place of GROUP BY.

Oracle 9i Sub query

Hi Can any one help me out of this query forming logic
SELECT C.CPPID, c.CPP_AMT_MANUAL
FROM CPP_PRCNT CC,CPP_VIEW c
WHERE
CC.CPPYR IN (
SELECT C.YEAR FROM CPP_VIEW_VIEW C WHERE UPPER(C.CPPNO) = UPPER('123')
AND C.CPP_CODE ='CPP000000000053'
and TO_CHAR(c.CPP_DATE,'YYYY/Mon')='2012/Nov'
)
AND UPPER(C.CPPNO) = UPPER('123')
AND C.CPP_CODE ='CPP000000000053'
and TO_CHAR(c.CPP_DATE,'YYYY/Mon') = '2012/Nov';
Please Correct me if i formed wrong query structure, in terms of query Performance and Standards. Thanks in Advance
If you have some indexes or partitioned tables I would not use functions on columns but on variables, to be able to use indexes/select partitions.
Also I use ANSI 92 SQL syntax. You don't specify(or not directly) a join contition between cpp_prcnt and cpp_view so it is actually a cartesian product(cross join)
SELECT C.CPPID, c.CPP_AMT_MANUAL
FROM CPP_PRCNT CC
CROSS JOIN CPP_VIEW c
WHERE
CC.CPPYR IN (
SELECT C.YEAR
FROM CPP_VIEW_VIEW C
WHERE C.CPPNO = '123'
AND C.CPP_CODE ='CPP000000000053'
AND trunc(c.CPP_DATE,'MM')=to_date('2012/Nov','YYYY/Mon')
)
AND C.CPPNO = '123'
AND C.CPP_CODE ='CPP000000000053'
AND trunc(c.CPP_DATE,'MM')=to_date('2012/Nov','YYYY/Mon')
If you show us the definition of cpp_view_view(seems to be a view over cpp_view), the definition(if simple) of CPP_VIEW and what you're trying to achieve, I bet there are more things to be improved/fixed.
There are a couple of things you could improve:
if possible, get rid of the UPPER() in the comparison - this will render any indices useless. If that's not possible, consider a function-based index on UPPER(CPPNO)
do not convert your DATE column to a string to compare it with a string - do it the other way round (i.e. convert your string to a date => only one conversion needed instead of one per table row, use of indices possible)
play around with EXISTS instead of IN, as suggested by Dileep - might be faster

Oracle Indexes on Left Outer Joins

So I'm having some issues with proper / any use of indexes in Oracle 11Gr2 and I'm trying to get a better understanding of how my explain plan ties back to my query so that I can apply indexing properly. When running the following query:
SELECT JLOG1.JLOG_KEY,
JLOG1.SRC_CD,
JLOG1.JRNL_AMT,
CASD.CONT_NO,
SUM (NVL (VJLOG.TDTL_AMT, 0)) TDTL_SUM
FROM GL_Journal_Logs JLOG1,
GL_JLOG_Details VJLOG,
CASE_DATA CASD
WHERE VJLOG.JLOG_KEY(+) = JLOG1.JLOG_KEY
AND CASD.CASE_KEY(+) = JLOG1.CASE_KEY
AND JLOG1.JRNL_CD = '0'
AND JLOG1.SRC_CD = '2'
AND JLOG1.ACCT_IF_CD = '0'
GROUP BY JLOG1.JLOG_KEY, JLOG1.SRC_CD,JLOG1.JRNL_AMT, CASD.CONT_NO
HAVING JLOG1.JRNL_AMT <> SUM (NVL (VJLOG.TDTL_AMT, 0));
I'm getting the following explain details:
I can understand that the indexes on my join "keys" (JLOG_KEY or CASE_KEY) wouldn't necessarily apply seeing as it's an outer join (or should they?), however when creating indexes on JLOG1 (JRNL_CD, SRC_CD, ACCT_IF_CD), technically would these take effect given my "where" clause?
Should I create any indexes at all given the circumstances or is there a better way of doing this?
Depending on the cardinality of the columns in your predicates, an appropriate index might be used on the GL_JLOG_DETAILS table, avoiding a full table scan. A covering index may avoid accessing the data pages at all:
ON GL_JOURNAL_LOGS (JRNL_CD,SRC_CD,ACCT_IF_CD,JLOG_KEY,CASE_KEY,JRNL_AMT)
(You probably want the column with the most selective predicate first in that index)
Also, your query may be able to make effective use of indexes
ON GL_JLOG_DETAILS (JLOG_KEY, TDTL_AMT)
and
ON CASE_DATA (CASE_KEY, CONT_NO)
Also, be sure that the statistics on the tables and indexes are up-to-date.
Also, that (+) notation for an OUTER JOIN may be limiting the optimizer.
Oracle now supports the ANSI style joins, which may allow the optimizer more latitude in coming up with an execution plan, e.g.
FROM GL_Journal_Logs JLOG1
LEFT
JOIN GL_JLOG_Details VJLOG ON VJLOG.JLOG_KEY = JLOG1.JLOG_KEY
LEFT
JOIN CASE_DATA CASD ON CASD.CASE_KEY = JLOG1.CASE_KEY
WHERE JLOG1.JRNL_CD = '0'
AND JLOG1.SRC_CD = '2'
AND JLOG1.ACCT_IF_CD = '0'

Is there an OR clause in LINQ?

I am trying to query an XML document for the specific records that I need. I know that the line containing the "or where" case below is incorrect, but I'm hoping it will illustrate what I am trying to accomplish. Can you do a conditional where clause on two seperate properties?
XDocument xd = XDocument.Load("CardData.xml");
SearchList.ItemsSource = from x in xd.Descendants("card")
where x.Element("title").Value.ToUpper().Contains(searchterm.ToUpper())
or where x.Element("id").Value.Contains(searchterm)
select new Card
{
Title = x.Element("title").Value
};
Yes - simply use the boolean or || and combine your conditions into one Where clause:
where x.Element("title").Value.ToUpper().Contains(searchterm.ToUpper()) ||
x.Element("id").Value.Contains(searchterm)
Also note just as a minor optimization, I would pre-compute some of the operations you currently have in your Where clause so they are not performed on every item in the list - probably doesn't matter but it might when you have a lot of elements (and is just a good habit to get into in my opinion):
string searchTermUpperCase = searchterm.ToUpper();
SearchList.ItemsSource = from x in xd.Descendants("card")
where x.Element("title").Value.ToUpper().Contains(searchTermUpperCase)
or where x.Element("id").Value.Contains(searchterm)
..

Resources