H2 DB - How to disable full group by - sql

There is a flag in mysql which enable/disable full group by (ONLY_FULL_GROUP_BY) But I am searching for same flag or connection string param to disable full group by in H2 database.
Here is my sample data.
+----+---------------+-----------------+
| ID | SYNC_ID | LIFECYCLE_EVENT |
+----+---------------+-----------------+
| 3 | 41 | 2 |
+----+---------------+-----------------+
| 2 | 41 | 1 |
+----+---------------+-----------------+
| 4 | 69 | 1 |
+----+---------------+-----------------+
| 5 | 69 | 3 |
+----+---------------+-----------------+
Here is my desired output:
+----+---------------+-----------------+
| ID | SYNC_ID | LIFECYCLE_EVENT |
+----+---------------+-----------------+
| 3 | 41 | 2 |
+----+---------------+-----------------+
| 5 | 69 | 3 |
+----+---------------+-----------------+
And Here is my query which I am trying to use for desired output
select id, sync_id, max(lifecycle_event)
from asset
where asset_type = 1
GROUP BY sync_id;
But it gives me ErrorCode: 90016 which means all non aggregate columns should be selected in group by. If I do so I get the wrong data results.
So Clearly I do not want to group by on id and sync_id . Please guide me how can I achieve this in H2 database.

There is no such thing in almost any other database -- because group by is not broken in those databases. You can phrase the query like this:
select a.*
from asset a
where asset_type = 1 and
lifecycle_event = (select max(lifecycle_event) from asset a2 where a2.sync_id = a.sync_id);

you can try below -
select max(id),sync_id, max(lifecycle_event)
from asset
where asset_type = 1
GROUP BY sync_id

I don't see any point in trying to emulate MySQL's broken group by implementation.
You can rewrite your query to
select a1.id, a1.sync_id, a2.max_even
from asset a1
join (
select sync_id, max(lifecycle_event) as max_event
from asset
group by sync_id
) a2 on a2.sync_id = a1.sync_id
and a2.max_event = a1.lifecycle_event;

Related

how to bake in a record count in a sql query

I have a query that looks like this:
select id, extension, count(distinct(id)) from publicids group by id,extension;
This is what the results looks like:
id | extension | count
-------------+-------------------------+-------
18459154909 | 12333 | 1
18459154909 | 9891114 | 1
18459154919 | 43244 | 1
18459154919 | 8776232 | 1
18766145025 | 12311 | 1
18766145025 | 1122111 | 1
18766145201 | 12422 | 1
18766145201 | 14141 | 1
But what I really want is for the results to look like this:
id | extension | count
-------------+-------------------------+-------
18459154909 | 12333 | 2
18459154909 | 9891114 | 2
18459154919 | 43244 | 2
18459154919 | 8776232 | 2
18766145025 | 12311 | 2
18766145025 | 1122111 | 2
18766145201 | 12422 | 2
18766145201 | 14141 | 2
I'm trying to get the count field to show the total number of records that have the same id.
Any suggestions would be appreciated
I think you want to count distincts extentions, not ids.
Run this query:
select id
, extension
(select count(*) from publicids p1 where p.id = p1.id ) distinct_id_count
from publicids p
group by id,extension;
This is more or less the same as Pastor's answer. Depending on what the optimizer does it might be faster with higher record count source tables.
select p.id, p.extension, p2.id_count
from publicids p
inner join (
select id, count(*) as id_count
from publicids group by id
) as p2 on p.id = p2.id

Query returned with an extra column in sql -ms access

So I am wondering. I fell into an interesting suggestion from another developer. So i basically have two tables I join in a query and I want the resulting table from the query to have an extra column that comes from the table on from the joint.
Example:
#table A: contains rating of players, changes randomly at any date depending
#on drop of form from the players
PID| Rating | DateChange |
1 | 2 | 10-May-2014 |
1 | 4 | 20-May-2015 |
1 | 20 | 1-June-2015 |
2 | 4 | 1-April-2014|
3 | 4 | 5-April-2014|
2 | 3 | 3-May-2015 |
#Table B: contains match sheets. Every player has a different match sheet
#and plays different dates.
MsID | PID | MatchDate | Win |
1 | 2 | 10-May-2014 | No |
2 | 1 | 15-May-2015 | Yes |
3 | 3 | 10-Apr-2014 | No |
4 | 1 | 21-Apr-2015 | Yes |
5 | 1 | 3-June-2015 | Yes |
6 | 2 | 5-May-2015 | No |
#I am trying to achieve this by running the ms-access query: i want to get
#every players rating at the time the match was played not his current
#rating.
MsID | PID | MatchDate | Rating |
1 | 2 | 10-May-2014 | 4 |
2 | 1 | 15-May-2015 | 2 |
3 | 3 | 10-Apr-2014 | 4 |
4 | 1 | 21-Apr-2015 | 4 |
5 | 1 | 3-June-2015 | 20 |
6 | 2 | 5-May-2015 | 3 |
This is what I have tried below:
Select MsID, PID, MatchDate, A-table.rating as Rating from B-table
left Join A-table
on B-table.PID = A-table.PID
where B-table.MatchDate > A-table.Datechange;
any help is appreciated. The solution can be in Vba as long as it returns something like a view/table I can manipulate using other queries or report.
Think of this in terms of sets of data... you need a set that lists the MAX dateChange for each player's and match date.
Soo...
SELECT MAX(A.DateChange) MDC, A.PID, B.Matchdate
FROM B-table B
INNER Join A-table A
on B.PID = A.PID
and A.DateChange <= B.MatchDate
GROUP BY A.PID, B.Matchdate
Now we take this and join it back to what you've done to limit the results in table A and B to ONLY those with that date player and matchDate (my inline table C)
SELECT B.MsID, B.PID, B.MatchDate, A.rating as Rating
FROM [B-table] B
INNER JOIN [A-table] A
on B.PID = A.PID
INNER JOIN (
SELECT MAX(Y.DateChange) MDC, Y.PID, Z.Matchdate
FROM [B-table] Z
INNER Join [A-table] Y
on Z.PID = Y.PID
and Y.DateChange <= Z.MatchDate
GROUP BY Y.PID, Z.Matchdate) C
on C.mdc = A.DateChange
and A.PID = C.PId
and B.MatchDate = C.Matchdate
I didn't create a sample for this using your data so it's untested but I believe the logic is sound...
Now Tested! SQL Fiddle using SQL server though...
My results don't match yours exactly. I think you're expected results are wrong though for MSID 4 given rules defined.

Looking for a solution to a SQL GROUP BY .... WHERE MIN date

EDIT: The following question is angled at both MS-SQL and MySQL.
I've been pondering over this for a good 7 hours now. I've seen many stack overflow answers that are similar, but none that i've properly understood or worked out how to implement.
I am looking to SELECT id, title, e.t.c e.t.c FROM a table, WHERE the date is the next available date AFTER NOW(). The catch is, it needs to be GROUPED BY one particular column.
Here is the table:
==================================
id | name | date_start | sequence_id
--------------------------------------------------------
1 | Foo1 | 20150520 | 70
2 | Foo2 | 20150521 | 70
3 | Foo3 | 20150522 | 70
4 | Foo4 | 20150523 | 70
5 | FooX | 20150524 | 70
6 | FooY | 20150525 | 70
7 | Bar | 20150821 | 61
8 | BarN | 20151110 | 43
9 | BarZ | 20151104 | 43
And here is what I would like to see:
==================================
id | name | date_start | sequence_id
--------------------------------------------------------
1 | Foo1 | 20150520 | 70
7 | Bar | 20150821 | 61
9 | BarZ | 20151104 | 43
The results are filtered by MIN(date_start) > NOW() AND GROUPED BY sequence_id.
I'm not entirely sure this can be achieved with a GROUP BY as the rest of the columns would need to be contained within an aggregate function which I don't think will work.
Does anyone have an answer for this dilemma?
Many Thanks!
Simon
Just use a join and aggregation in a subquery:
select t.*
from table t join
(select sequence_id, min(date_start) as minds
from table t
group by sequence_id
) tt
on tt.sequence_id = t.sequence_id and t.date_start = tt.minds;
This is standard SQL, so it should run in any database.
http://sqlfiddle.com/#!9/d8576/4
SELECT *
FROM table1 as t1
LEFT JOIN
(SELECT *
FROM table1
WHERE date_start>NOW()
) as t2
ON t1.sequence_id = t2.sequence_id and t1.date_start>t2.date_start
WHERE t1.date_start>NOW() and t2.date_start IS NULL
GROUP BY t1.sequence_id
MSSQL fiddle
SELECT *
FROM table1 as t1
LEFT JOIN
(SELECT *
FROM table1
WHERE date_start>GetDate()
) as t2
ON t1.sequence_id = t2.sequence_id and t1.date_start>t2.date_start
WHERE t1.date_start>GetDate() and t2.date_start IS NULL

Need help writing recursive query

I have a table in access with the following format:-
ID | Name | Qty
----+--------+------
1 | A1 | 10
2 | A2 | 20
3 | A1 | 30
4 | A2 | 40
5 | A1 | 50
----+--------+------
I want to run a query which will return the sum of Qty for each row above it where the Name matches. So, the Output will be :-
ID | Name | Output
----+--------+---------
1 | A1 | 0
2 | A2 | 0
3 | A1 | 10
4 | A2 | 20
5 | A1 | 40
----+--------+----------
I am not being able to write the query. I think I need some kind of recursive query, but I'm not very well versed in SQL/Databases.
Access does not support recursion. The following query should do what you want (i called your table NameQty):
SELECT t1.Id,t1.name,sum(t2.Qty)
FROM NameQty t1
LEFT JOIN NameQty t2 ON t1.name=t2.name AND t1.Id>t2.Id
GROUP BY t1.Id,t1.name
ORDER BY t1.Id
I think you should also use some other column than ID for the definition of "above".

How to write a Sql query to find distinct values that have never met the following "Where Not(a=x and b=x)"

I have the following table called Attributes
* AttId * CustomerId * Class * Code *
| 1 | 1 | 1 | AA |
| 2 | 1 | 1 | AB |
| 3 | 1 | 1 | AC |
| 4 | 1 | 2 | AA |
| 5 | 1 | 2 | AB |
| 6 | 1 | 3 | AB |
| 7 | 2 | 1 | AA |
| 8 | 2 | 1 | AC |
| 9 | 2 | 2 | AA |
| 10 | 3 | 1 | AB |
| 11 | 3 | 3 | AB |
| 12 | 4 | 1 | AA |
| 13 | 4 | 2 | AA |
| 14 | 4 | 2 | AB |
| 15 | 4 | 3 | AB |
Where each Class, Code pairing represents a specific Attribute.
I'm trying to write a query that returns all customers that are NOT linked to the Attribute pairing Class = 1, Code = AB.
This would return Customer Id values 2 and 4.
I started to write Select Distinct A.CustomerId From Attributes A Where (A.Class = 1 and A.Code = 'AB') but stopped when I realised I was writing a SQL query and there is not an operator available to place before the parentheses to indicate the clause within must Not be met.
What am I missing? Or which operator should I be looking at?
Edit:
I'm trying to write a query that only returns those Customers (ie distinct Customer Id's) that have NO link to the Attribute pairing Class = 1, Code = AB.
This could only be Customer Id values 2 and 4 as the table does Not contain the rows:
* AttId * CustomerId * Class * Code *
| x | 2 | 1 | AB |
| x | 4 | 1 | AB |
Changed Title from:
How to write "Where Not(a=x and b=x)"in Sql Query
To:
How to write a Sql query to find distinct values that have never met the following "Where Not(a=x and b=x)"
As the previous title was a question in it's own right however the detail of the question added an extra dimension which led to confusion.
One way would be
SELECT DISTINCT CustomerId FROM Attributes a
WHERE NOT EXISTS (
SELECT * FROM Attributes forbidden
WHERE forbidden.CustomerId = a.CustomerId AND forbidden.Class = _forbiddenClassValue_ AND forbidden.Code = _forbiddenCodeValue_
)
or with join
SELECT DISTINCT a.CustomerId FROM Attributes a
LEFT JOIN (
SELECT CustomerId FROM Attributes
WHERE Class = _forbiddenClassValue_ AND Code = _forbiddenCodeValue_
) havingForbiddenPair ON a.CustomerId = havingForbiddenPair.CustomerId
WHERE havingForbiddenPair.CustomerId IS NULL
Yet another way is to use EXCEPT, as per ypercube's answer
SELECT CustomerId
FROM Attributes
EXCEPT
SELECT CustomerId
FROM Attributes
WHERE Class = 1
AND Code = AB ;
Since no one has posted the simple logical statement, here it is:
select . . .
where A.Class <> 1 OR A.Code <> 'AB'
The negative of (X and Y) is (not X or not Y).
I see, this is a grouping thing. For this, you use aggregation and having:
select customerId
from Attributes a
group by CustomerId
having sum(case when A.Class = 1 and A.Code = 'AB' then 1 else 0 end) = 0
I always prefer to solve "is it in a set" type questions using this technique.
Select Distinct A.CustomerId From Attributes A Where not (A.Class = 1 and A.Code = 'AB')
Try this:
SELECT DISTINCT A.CustomerId From Attributes A Where
0 = CASE
WHEN A.Class = 1 and A.Code = 'AB' THEN 1
ELSE 0
END
Edit: of course this still gives you cust 1 (doh!), you should probably use pjotrs NOT EXISTS query ideally, serves me right for not looking at the data closely enough :)