GROUP BY in Informix (11.5) - sql

Following Example Table Structure:
NR1 | NR2 | PRENAME | LASTNAME
If i query all 4 fields of this table and grouping it´s first 2 fields (NR1,NR2) in mysql,
i can do something like this:
SELECT NR1,NR2,PRENAME,LASTNAME FROM tbl GROUP BY NR1,NR1
But this won´t work in informix.
INFORMIX ERROR: the column (PRENAME) must be in the group by list
After reading some Topics at google, it is an "Informix feature" that all Selected Columns has to be in the Grouping List.
But if i will do that, the result is not that result, that i wish to have.
If i use
DISTINCT
instead GROUP BY the result is similar false, because i can not put the DISTINCTfunction only to column 1 and 2.
So: How can i make a "MYSQL GROUP BY" function ?

Your original syntax is suitable in one database -- MySQL. And, that database says that the results of the non-aggregated columns come from indeterminate rows. So, an equivalent query is just to use MIN() or MAX():
SELECT NR1, NR2, MIN(PRENAME), MIN(LASTNAME)
FROM tbl
GROUP BY NR1, NR1;
My guess is that you want an arbitrary value from just one row. I'd be inclined to concatenate them:
SELECT NR1, NR2, MIN(PRENAME || ' ' || LASTNAME)
FROM tbl
GROUP BY NR1, NR1;

Related

using having in where clause

If I have the following table:
my_table:
varchar name
int score
and I want to do the following query:
select name from my_table group by name having count(*)>3
union
select name from my_table where name like '%xyz'
Is there a way doing this query without a union?
To be clear: I want all names which have more than three entries in the table OR answer the like clause '%xyz'.
The below query will only grab names that match the like clause before grouping:
SELECT name,count(*) as num FROM my_table GROUP BY name HAVING num > 3 OR name like '%xyz'
EDIT: The above query has been altered to allow for either the name or the num clauses to cause the row to be accepted.
Unions are only used when linking two tables.
I think you are looking for something like this?
SELECT name,count(*) as num
FROM my_table
GROUP BY name
HAVING num > 3 OR name like '%xyz'
http://sqlfiddle.com/#!9/1b6a0/2/0
Edited to match OP's question after reading intended results.
select name,count(*) as num
from my_table
group by name having num>3
where name like '%xyz'

"group by" needed in count(*) SQL statement?

The following statement works in my database:
select column_a, count(*) from my_schema.my_table group by 1;
but this one doesn't:
select column_a, count(*) from my_schema.my_table;
I get the error:
ERROR: column "my_table.column_a" must appear in the GROUP BY clause
or be used in an aggregate function
Helpful note: This thread: What does SQL clause "GROUP BY 1" mean? discusses the meaning of "group by 1".
Update:
The reason why I am confused is because I have often seen count(*) as follows:
select count(*) from my_schema.my_table
where there is no group by statement. Is COUNT always required to be followed by group by? Is the group by statement implicit in this case?
This error makes perfect sense. COUNT is an "aggregate" function. So you need to tell it which field to aggregate by, which is done with the GROUP BY clause.
The one which probably makes most sense in your case would be:
SELECT column_a, COUNT(*) FROM my_schema.my_table GROUP BY column_a;
If you only use the COUNT(*) clause, you are asking to return the complete number of rows, instead of aggregating by another condition. Your questing if GROUP BY is implicit in that case, could be answered with: "sort of": If you don't specify anything is a bit like asking: "group by nothing", which means you will get one huge aggregate, which is the whole table.
As an example, executing:
SELECT COUNT(*) FROM table;
will show you the number of rows in that table, whereas:
SELECT col_a, COUNT(*) FROM table GROUP BY col_a;
will show you the the number of rows per value of col_a. Something like:
col_a | COUNT(*)
---------+----------------
value1 | 100
value2 | 10
value3 | 123
You also should take into account that the * means to count everything. Including NULLs! If you want to count a specific condition, you should use COUNT(expression)! See the docs about aggragate functions for more details on this topic.
If you don't use the Group by clause at all then all that will be returned is a count of 1 for each row, which is already assumed anyway and therefore redundant data. By adding GROUP BY 1 you have categorized the information thereby making it non-redundant even though it returns the same result in theory as the statement that creates an error.
When you have a function like count, sum etc. you need to group the other columns. This would be equivalent to your query:
select column_a, count(*) from my_schema.my_table group by column_a;
When you use count(*) with no other column, you are counting all rows from SELECT * from the table. When you use count(*) alongside another column, you are counting the number of rows for each different value of that other column. So in this case you need to group the results, in order to show each value and its count only once.
group by 1 in this case refers to column_a which has the column position 1 in your query.
This why it works on your server. Indeed this is not a good practice in sql.
You should mention the column name because the column order may change in the table so it will be hard to maintain this code.
The best solution is:
select column_a, count(*) from my_schema.my_table group by column_a;

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 Having on columns not in SELECT

I have a table with 3 columns:
userid mac_address count
The entries for one user could look like this:
57193 001122334455 42
57193 000C6ED211E6 15
57193 FFFFFFFFFFFF 2
I want to create a view that displays only those MAC's that are considered "commonly used" for this user. For example, I want to filter out the MAC's that are used <10% compared to the most used MAC-address for that user. Furthermore I want 1 row per user. This could easily be achieved with a GROUP BY, HAVING & GROUP_CONCAT:
SELECT userid, GROUP_CONCAT(mac_address SEPARATOR ',') AS macs, count
FROM mactable
GROUP BY userid
HAVING count*10 >= MAX(count)
And indeed, the result is as follows:
57193 001122334455,000C6ED211E6 42
However I really don't want the count-column in my view. But if I take it out of the SELECT statement, I get the following error:
#1054 - Unknown column 'count' in 'having clause'
Is there any way I can perform this operation without being forced to have a nasty count-column in my view? I know I can probably do it using inner queries, but I would like to avoid doing that for performance reasons.
Your help is very much appreciated!
As HAVING explicitly refers to the column names in the select list, it is not possible what you want.
However, you can use your select as a subselect to a select that returns only the rows you want to have.
SELECT a.userid, a.macs
FROM
(
SELECT userid, GROUP_CONCAT(mac_address SEPARATOR ',') AS macs, count
FROM mactable
GROUP BY userid
HAVING count*10 >= MAX(count)
) as a
UPDATE:
Because of a limitation of MySQL this is not possible, although it works in other DBMS like Oracle.
One solution would be to create a view for the subquery. Another solution seems cleaner:
CREATE VIEW YOUR_VIEW (userid, macs) AS
SELECT userid, GROUP_CONCAT(mac_address SEPARATOR ',') AS macs, count
FROM mactable
GROUP BY userid
HAVING count*10 >= MAX(count)
This will declare the view as returning only the columns userid and macs although the underlying SELECT statement returns more columns than those two.
Although I am not sure, whether the non-DBMS MySQL supports this or not...

sqlite get records with same column value

I have a SQLite DB that has people LastName, FirstName, Department and I need to make a query that shows me any people with the same First & Last Names. I've found the following statement that supposedly does what I want for a single field, however it doesn't seem to work for me when I try to use it to pull all records with just the last name being the same. How can I do this?
Select myField From myTable Group by myField Where count(myField)>1
try:
Select
firstname,LastName,Count(*)
From myTable
Group by firstname,LastName
HAVING Count(*)>1
GROUP BY combines rows where the named values are the same.
HAVING removes groups that do not meet the condition.
The above query will list the first and last names, along with a count of duplicates for all first/last names that actually have duplicates.
Firstly, you need to use HAVING, not WHERE to qualify the GROUPed BY result:
SELECT myField FROM myTable GROUP BY myField HAVING COUNT(myField) > 1
Secondly, you can extend this to multiple columns like this:
SELECT MyCol1, MyCol2 FROM MyTable
GROUP BY MyCol1, MyCol2
HAVING COUNT(*) > 1