HQL count from multiple tables - sql

I would like to query my database using a HQL query to retrieve the total number of rows having a MY_DATE greater than SOME_DATE.
So far, I have come up with a native Oracle query to get that result, but I am stuck when writing in HQL:
SELECT
(
SELECT COUNT(MY_DATE)
FROM Table1
WHERE MY_DATE >= TO_DATE('2011-09-07','yyyy-MM-dd')
)
+
(
SELECT COUNT(MY_DATE)
FROM Table2
WHERE MY_DATE >= TO_DATE('2011-09-07','yyyy-MM-dd')
)
AS total
I actually have more than 2 tables but I keep having an IllegalArgumentException (unexpected end of subtree).
The working native Oracle basically ends with FROM dual.
What HQL query should I use to get the total number of rows I want?

First of, if you have a working SQL query, why not just use that instead of trying to translate it to HQL? Since you're returning a single scalar in the first place, it's not like you need anything HQL provides (e.g. dependent entities, etc...)
Secondly, do you have 'dual' mapped in Hibernate? :-) If not, how exactly are you planning on translating that?
That said, "unexpected end of subtree" error is usually caused by idiosyncrasies of Hibernate's AST parser. A commonly used workaround is to prefix the expression with '0 +':
select 0 + (
... nested select #1 ...
) + (
... nested select #2 ...
) as total
from <from what exactly?>

Related

Matching multiple columns in a nested query

I'm trying to make a nested query, where I return values from multiple columns and match those with values from another column. Something similar to the code below (this is for work so I can't put the exact code here)
select *
from store1
where (orderNum, customer, total) not in (
select orderNum, customer, total from store2)
When I try to run the code, I get the error:
An expression of non-boolean type specified in a context where a condition is expected, near ','.
Is there a way to do this is SQL Server. I know using a join is an option but I'd prefer to avoid that at this time. Thanks for any help!
SQL Server doesn't support table constructors like that, but there are lots of other ways to do it. My preferred approach is NOT EXISTS:
SELECT * FROM dbo.store1
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.store2
WHERE store1.orderNum = store2.orderNum
AND store1.customer = store2.customer
AND store1.total = store2.total
);
For other approaches, see:
Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
"count" returns a single value, works fast. Easy to understand.
select *
from store1
where
(select count(*) from store2 where store2.orderNum=store1.orderNum and store2.customer=store1.customer and store2.total=store1.total)=0

How to use multiple count distinct in the same query with other columns in Druid SQL?

I'm trying to use three projections in same query like below in a Druid environment:
select
__time,
count(distinct col1),
count(distinct case when (condition1 and condition2 then (concat(col2,TIME_FORMAT(__time))) else 0 end )
from table
where condition3
GROUP BY __time
But instead I get an error saying - Unknown exception / Cannot build plan for query
It seems to work perfectly fine when I put just one count(distinct) in the query.
How can this be resolved?
As a workaround, you can do multiple subqueries and join them. Something like:
SELECT x.__time, x.delete_cnt, y.added_cnt
FROM
(
SELECT FLOOR(__time to HOUR) __time, count(distinct deleted) delete_cnt
FROM wikipedia
GROUP BY 1
)x
JOIN
(
SELECT FLOOR(__time to HOUR) __time, count( distinct added) added_cnt
FROM wikipedia
GROUP BY 1
)y ON x.__time = y.__time
As the Druid documentation points out:
COUNT(DISTINCT expr) Counts distinct values of expr, which can be string, numeric, or hyperUnique. By default this is approximate, using a variant of HyperLogLog. To get exact counts set "useApproximateCountDistinct" to "false". If you do this, expr must be string or numeric, since exact counts are not possible using hyperUnique columns. See also APPROX_COUNT_DISTINCT(expr). In exact mode, only one distinct count per query is permitted.
So this is a Druid limitation: you either need to disable exact mode, or else limit yourself to one distinct count per query.
On a side note, other databases typically do not have this limitation. Apache Druid is designed for high performance real-time analytics, and as a result, its implementation of SQL has some restrictions. Internally, Druid uses a JSON-based query language. The SQL interface is powered by a parser and planner based on Apache Calcitea, which translates SQL into native Druid queries.

Use Ruby To Convert Any Query To Count Query

In my application I use PG to execute queries defined by the user in-app.
require 'pg'
database = PG.connect(*credentials)
query = 'select id, created_at from users where id % 2 = 0'
database.connection.exec(query)
Part of the application requires fetching a count before running the actual query so I use regex to convert the query to a count query. (Assume LIMIT and ORDER BY are not allowed)
query = 'select id, created_at from users where id % 2 = 0'
query.gsub!(%r{(?<=SELECT)[^\/]+(?=FROM)}, ' count(*) ')
count = database.exec(query).first['count'].to_i
But if the query includes CTE's and/or sub-queries...
query = 'with new_table as (select id from users where id % 2 = 0)
select created_at, name from users where id in (select * from new_table)'
the above regex doesn't work, and I haven't been able to figure out another regex based solution.
Using SQL, Ruby, or REGEX, how could I convert any query a read-only db user could perform into a count query WITHOUT wrapping the query in its own CTE or just running the query and counting the results?
More simply, given a query, how can one get the row count for that query without actually running the full query?
Any engineers at Looker, PeriscopeData, or Mode should have this one in the bag :-)
Modifying SQL queries with a regex is a non-starter for all the reasons you don't try to modify XML with a regex: you need something which understands the grammar. What you're looking for is a SQL Query Builder.
A SQL Query Builder is sort of like an ORM without the ORM. You use it to write SQL queries using method calls, not strings, but you don't have to tell it what all your tables and columns are like an ORM, nor do you have to make classes for all your tables. It just makes SQL queries.
Your query is held as an object and only turned into SQL when it's time to communicate with the database. If you want to modify the query, you do it with method calls and regenerate the SQL. So you can add where clauses and group bys and limits and add more rows to select and join tables and, yes, count.
They also will often smooth over SQL incompatibilities for you, so the same code can run on MySQL or SQLite or Postgresql or Oracle.
A good non-Ruby one is Knex.js in Javascript. I'm having a hard time finding a pure SQL Query Builder for Ruby. The ones I've found (ActiveRecord, Sequel, squeel, and ARel) are all ORMs and require you to set up classes and schemas and all that. The only one I could find for Ruby that isn't an ORM is qdsl.
Easy way: create a new query from your existing one by just surrounding it to convert it into a subquery:
require 'pg'
database = PG.connect(*credentials)
query = 'select id, created_at from users where id % 2 = 0'
# Create a `count` query, based on the existing one.
# The original query must NOT end with ';'
count_query = 'SELECT count(*) AS count FROM (' + query + ') AS q0'
database.connection.exec(count_query)
# Follow on
database.connection.exec(query)
This may not be the most efficient way of getting the count, but I think it is the simplest and (probably) the less error-prone. It assumes that the original query is well-formed, and that it does not call functions with side-effects [a practice that should be reserved for very few use-cases].
Assuming the users table is similar to:
CREATE TABLE users AS
SELECT * FROM
(VALUES
(1::integer, 'name1'::text, now()::timestamp),
(2, 'name2', now() - interval '1 hour'),
(3, 'name3', now() - interval '2 hours'),
(4, 'name4', now() - interval '2 hours')
) x(id, name, created_at) ;
This solution works with WITH clases, because the following SQL query is legal:
SELECT count(*) FROM
(
with new_table as (select id from users where id % 2 = 0)
select created_at, name from users where id in (select * from new_table)
) AS q0 ;
... and returns 2 as expected.

counting rows in select clause with DB2

I would like to query a DB2 table and get all the results of a query in addition to all of the rows returned by the select statement in a separate column.
E.g., if the table contains columns 'id' and 'user_id', assuming 100 rows, the result of the query would appear in this format: (id) | (user_id) | 100.
I do not wish to use a 'group by' clause in the query. (Just in case you are confused about what i am asking) Also, I could not find an example here: http://mysite.verizon.net/Graeme_Birchall/cookbook/DB2V97CK.PDF.
Also, if there is a more efficient way of getting both these results (values + count), I would welcome any ideas. My environment uses zend framework 1.x, which does not have an ODBC adapter for DB2. (See issue http://framework.zend.com/issues/browse/ZF-905.)
If I understand what you are asking for, then the answer should be
select t.*, g.tally
from mytable t,
(select count(*) as tally
from mytable
) as g;
If this is not what you want, then please give an actual example of desired output, supposing there are 3 to 5 records, so that we can see exactly what you want.
You would use window/analytic functions for this:
select t.*, count(*) over() as NumRows
from table t;
This will work for whatever kind of query you have.

SQL Query Syntax : Using table alias in a count is invalid? Why?

Could someone please explain to me why the following query is invalid? I'm running this query against an Oracle 10g database.
select count(test.*) from my_table test;
I get the following error: ORA-01747: invalid user.table.column, table.column, or column specification
however, the following two queries are valid.
select count(test.column) from my_table test;
select test.* from my_table test;
COUNT(expression) will count all rows where expression is not null. COUNT(*) is an exception, it returns the number of rows: * is not an alias for my_table.*.
As far as I know, Count(Table.*) is not officially supported in the SQL specification. Only Count(*) (count all rows returned) and Count(Table.ColumnName) (count all non-null values in the given column). So, even if the DBMS supported it, I would recommend against using it.`
This syntax only works in PostgreSQL and only because it has a record datatype (for which test.* is a meaningful expression).
Just use COUNT(*).
This query:
select count(test.column) from my_table test;
will return you the number of records for which test.column is not NULL.
This query:
select test.* from my_table test;
will just return you all records from my_table.
COUNT as such is probably the only aggregate that makes sense without parameters, and using an expression like COUNT(*) is just a way to call a function without providing any actual parameters to it.
You might reasonably want to find the number of records where test.column is not NULL if you are doing an outer join. As every table should have a PK (which is not null) you should be able to count the rows like that if you want:
select count(y.pk)
from x
left outer join y on y.pk = x.ck
COUNT(*) is no good here because the outer join is creating a null row for the table that is deficient in information.