Vários GROUP BY MySql - mysql

I'm trying to mount the sql that does the following query, in the TYPE field there are both type CUT and RELIANCE, but I need each of them to come in a column, but only I can now show it in each one in a line is possible to do so?
SELECT id_user, date_conclusion, type, COUNT (*)
FROM the
WHERE id_user = 8 and date_conclusion LIKE '2017-12%'
GROUP by date_conclusion, type

Assuming that only these two types exist. You do not need the extra type column then:
SELECT
id_user,
date_conclusion,
SUM(type = 'CORTE') AS 'CORTE',
SUM(type = 'RELIGACAO') AS 'RELIGACAO'
FROM
the
WHERE
id_user = 8 AND
date_conclusion LIKE '2017-12%'
GROUP BY
date_conclusion

Related

Create new unique value in column

I have a (MYSQL) table in the following format; assume the name of the table is mytable:
id
name
group
123
name1
1
124
name2
2
125
name3
1
126
name4
id is unique and auto-increments. name is a unique string, group is just an integer
I now want to assign name4 to a new group that does not exist yet, so the group for name4cannot be 1 or 2 in this example.
The result could,for example, be:
id
name
group
126
name4
3
At the moment I am sorting by group descending and just insert the highest number + 1 manually, but I was wondering if there was a better/quicker way to generate a new, unique value in a column. group has no other constraints, besides being an integer.
I am using the MySQL Workbench, so I can work with both SQL commands, as well as Workbench-specific options, if there are any.
If anything is unclear I'll gladly provide clarification.
In MySQL 8.0, you can get help with two window functions:
MAX, to retrieve the maximum "group" value
ROW_NUMBER, to retrieve the incremental value for each NULL existing in your table.
You can then sum up these two values and update your table where your "group" field is null.
WITH cte AS (
SELECT id, name, MAX(group_) OVER() + ROW_NUMBER() OVER(PARTITION BY group_ IS NULL ORDER BY name) AS new_group
FROM tab
)
UPDATE tab
INNER JOIN cte
ON tab.id = cte.id AND tab.name = cte.name
SET tab.group_ = cte.new_group
WHERE tab.group_ IS NULL;
Check the demo here.
In MySQL 5.X you can instead use a variable, initialized with your maximum "group" value, then updated incrementally inside the UPDATE statement, in the SET clause.
SET #maxgroup = NULL;
SELECT MAX(group_) INTO #maxgroup FROM tab;
UPDATE tab
SET group_ = (#maxgroup:= #maxgroup + 1)
WHERE group_ IS NULL;
ORDER BY id;
Check the demo here.

MYSQL The used SELECT statements have a different number of columns

I need to combined 2 tables with the same ids in it but i can't
SELECT stat.user_id, user.username,
SUM(stat.vertrag) AS vertrag,
SUM(stat.zubehoer) AS zubehoer,
SUM(stat.privat) AS privat,
SUM(stat.service) AS service,
SUM(stat.bs_vertrag) AS bus
FROM statistics stat
join users user on stat.user_id = user.uid
WHERE stat.user_id != '0' AND stat.datum LIKE '%$month%'
GROUP BY stat.user_id
UNION
SELECT bew.user_id, stat.user_id, user.username,
SUM(case when bew.log = 'inv_imei'
THEN
1
ELSE
0
END) AS inv
FROM user_bewegungen bew
JOIN users user ON user.uid = bew.user_id
JOIN statistics stat ON bew.user_id = stat.user_id
WHERE bew.date LIKE '%$month%'
GROUP BY bew.user_id
ORDER BY vertrag DESC
I am dont know how to go now.....
The first select is perfect, and works. now i have add a union because i need to add the row "log". Id's are also in it but i become the error
The used SELECT statements have a different number of columns
Can anyone help?
Each select statement needs to have the same number of columns. Your first one has 7:
SELECT
stat.user_id,
user.username,
SUM(stat.vertrag) AS vertrag,
SUM(stat.zubehoer) AS zubehoer,
SUM(stat.privat) AS privat,
SUM(stat.service) AS service,
SUM(stat.bs_vertrag) AS bus
Your second one has 4:
SELECT
bew.user_id,
stat.user_id,
user.username,
SUM(case when bew.log = 'inv_imei' THEN 1 ELSE 0 END) AS inv
You can select NULL in the second SELECT for those columns that aren't in the first one.
Make the two operands of the UNION isomorphic. Rename columns and/or create NULL-valued dummy columns as necessary to give them the same shape. FOR EXAMPLE, if we wanted to form the UNION of:
SELECT a, b, c
FROM table1
and:
SELECT d, e
FROM table2
we would logically pair those columns that are of the same types (in this case, let's assume that a and e are of the same type, and that b and d are of the same type) and add an extra NULL-valued column as the third projected attribute of the right-hand SELECT, as follows:
SELECT b, a, c
FROM table1
UNION
SELECT d AS b, e AS a, NULL as c
FROM table2
If such an approach seems confusing, you can use table views to simplify the expression. In the preceding example, you could have asserted a view atop table2:
CREATE VIEW t2view( b, a, c )
AS
SELECT d, e, NULL
FROM table2
and then formulated your UNION as:
SELECT b, a, c
FROM table1
UNION
SELECT *
FROM t2view
In UNION, the field numbers should be the same. Use like this:
SELECT stat.user_id, 0, user.username, ....
SELECT bew.user_id, stat.user_id, user.username, ...
or use something else, what you know, that is a missing field there.
The data types should be the same also.
You are using MySQL Union.
UNION is used to combine the result from multiple SELECT statements into a single result set.
The column names from the first SELECT statement are used as the column names for the results returned. Selected columns listed in corresponding positions of each SELECT statement should have the same data type. (For example, the first column selected by the first statement should have the same type as the first column selected by the other statements.)
Reference: MySQL Union
Your first select statement has 7 columns and second statement has 4.
You should have same number of column and also in same order in both statement.
otherwise it shows error or wrong data.
you can see this example
there are two queries both queries have the same number of columns.
column name can be different.
select 'row1' as column1,'row2' as column2
union
select 'row3' as column11,'row4' as column222
if you change columns count, it means in first query you are selecting 2 columns and in second query you are using 3 columns then it will through an error (The used SELECT statements have a different number of columns).
select 'row1' as column1,'row2' as column2
union
select 'row3' as column11,'row4' as column222 ,'rr' as t ;
run both queries you will see differnce.

Query different table when column exist

Database: MySql 5.5.3
I have a type column in table topic, if the type is 'E' which means there is an entry exist in 'Event' Table and it should query "TOPIC_HAS_EVENT" table to get few more colums from the EVENT Table. In the same way if Type is 'P' which means there is an entry exist in 'Poll Table' and it should query "TOPIC_HAS_POLL" table to get few columns from POLL Table. If the type is null then it should query as usual to get all the rows and their comments from the comment table.
The end results should have all the topics rows of all types ('E','P', NULL) and their specific columns from other table. If that can accomplish easily then i need to add few more columns as mentioned below
More complex
If type='E' have some rows, it should get some more rows such as user information from EVENT_HAS_USER table.
Relationship
Each Topic has Many Comments
Each Topic has One Event
Each Topic has One Poll
EVENT ManyTOMany User
Query so far created. I still need to add 'type' column. Please help me with it.
SELECT DISTINCT
T.TOPIC_GUID, COUNT(*) TOTAL_COMMENTS
FROM
CIRCLE C, CIRCLE_HAS_USER CHU, CIRCLE_HAS_TOPIC CHT, TOPIC T
LEFT JOIN TOPIC_COMMENT TC ON T.TOPIC_GUID = TC.TOPIC_GUID
WHERE
CHT.CIRCLE_GUID = C.CIRCLE_GUID
AND T.TOPIC_GUID < 400000 -- ?
AND CHT.TOPIC_GUID = T.TOPIC_GUID
AND CHU.CIRCLE_GUID = C.CIRCLE_GUID
AND CHU.USER_GUID = 1
AND CHU.STATUS = 'A'
GROUP BY T.TOPIC_GUID
ORDER BY T.LAST_UPDATED_TIMESTAMP DESC
LIMIT 10
Try this:
select (case when type = 'type1' then (select field from table1) else (select field from table2) end) as a from table;

Error "Ambiguous column name SubscriberKey"

Select A.SubscriberKey, COUNT(DISTINCT EventDate) AS Count,B.CreatedDate
From _Open A
JOIN _ListSubscribers B
ON A.SubscriberKey = B.SubscriberKey
Where B.ListID = '10630'
Group By SubscriberKey
HAVING COUNT(DISTINCT EventDate) = 1
You need to specify the table that the column comes from as the same column name exists in both tables.
i.e. use Group By A.SubscriberKey as that is what you have in the SELECT list.
Also all RDBMSs except for MySQL will require you to also add B.CreatedDate to the GROUP BY list as that is in the SELECT list
You have more than one table that contains a column named after that name, so you need to specify the table containing the column referred to in your Group By SubscriberKey:
Group By A.SubscriberKey

How to find the next record after a specified one in SQL?

I'd like to use a single SQL query (in MySQL) to find the record which comes after one that I specify.
I.e., if the table has:
id, fruit
-- -----
1 apples
2 pears
3 oranges
I'd like to be able to do a query like:
SELECT * FROM table where previous_record has id=1 order by id;
(clearly that's not real SQL syntax, I'm just using pseudo-SQL to illustrate what I'm trying to achieve)
which would return:
2, pears
My current solution is just to fetch all the records, and look through them in PHP, but that's slower than I'd like. Is there a quicker way to do it?
I'd be happy with something that returned two rows -- i.e. the one with the specified value and the following row.
EDIT: Sorry, my question was badly worded. Unfortunately, my definition of "next" is not based on ID, but on alphabetical order of fruit name. Hence, my example above is wrong, and should return oranges, as it comes alphabetically next after apples. Is there a way to do the comparison on strings instead of ids?
After the question's edit and the simplification below, we can change it to
SELECT id FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
SELECT * FROM table WHERE id > 1 ORDER BY id LIMIT 1
Even simpler
UPDATE:
SELECT * FROM table WHERE fruit > 'apples' ORDER BY fruit LIMIT 1
So simple, and no gymnastics required
Select * from Table
where id =
(Select Max(id) from Table
where id < #Id)
or, based on the string #fruitName = 'apples', or 'oranges' etc...
Select * from Table
where id =
(Select Max(id) from Table
where id < (Select id from Table
Where fruit = #fruitName))
I'm not familiar with the MySQL syntax, but with SQL Server you can do something with "top", for example:
SELECT TOP 1 * FROM table WHERE id > 1 ORDER BY id;
This assumes that the id field is unique. If it is not unique (say, a foreign key), you can do something similar and then join back against the same table.
Since I don't use MySQL, I am not sure of the syntax, but would imagine it to be similar.
Unless you specify a sort order, I don't believe the concepts of "previous" or "next" are available to you in SQL. You aren't guaranteed a particular order by the RDBMS by default. If you can sort by some column into ascending or descending order that's another matter.
This should work. The string 'apples' will need to be a parameter.
Fill in that parameter with a string, and this query will return the entire record for the first fruit after that item, in alphabetical order.
Unlike the LIMIT 1 approach, this should be platform-independent.
--STEP THREE: Get the full record w/the ID we found in step 2
select *
from
fruits fr
,(
--STEP TWO: Get the ID # of the name we found in step 1
select
min(vendor_id) min_id
from
fruits fr1
,(
--STEP ONE: Get the next name after "apples"
select min(name) next_name
from fruits frx
where frx.name > 'apples'
) minval
where fr1.name = minval.next_name
) x
where fr.vendor_id = x.min_id;
The equivalent to the LIMIT 1 approach in Oracle (just for reference) would be this:
select *
from
(
select *
from fruits frx
where frx.name > 'apples'
order by name
)
where rownum = 1
I don't know MySQL SQL but I still try
select n.id
from fruit n
, fruit p
where n.id = p.id + 1;
edit:
select n.id, n.fruitname
from fruits n
, fruits p
where n.id = p.id + 1;
edit two:
Jason Lepack has said that that doesn't work when there are gaps and that is true and I should read the question better.
I should have used analytics to sort the results on fruitname
select id
, fruitname
, lead(id) over (order by fruitname) id_next
, lead(fruitname) over (order by fruitname) fruitname_next
from fruits;
If you are using MS SQL Server 2008 (not sure if available for previous versions)...
In the event that you are trying to find the next record and you do not have a unique ID to reference in an applicable manner, try using ROW_NUMBER(). See this link
Depending on how savvy your T-SQL skill is, you can create row numbers based on your sorting order. Then you can find more than just the previous and next record. Utilize it in views or sub-queries to find another record relative to the current record's row number.
SELECT cur.id as id, nxt.id as nextId, prev.id as prevId FROM video as cur
LEFT JOIN video as nxt ON nxt.id > cur.id
LEFT JOIN video as prev ON prev.id < cur.id
WHERE cur.id = 12
ORDER BY prev.id DESC, nxt.id ASC
LIMIT 1
If you want the item with previous and next item this query lets you do just that.
This also allows You to have gaps in the data!
How about this:
Select * from table where id = 1 + 1