Mysql query only select rows with unique result within GROUP_CONCAT - mysql

Is there a way to select only the rows that have an other result than the row previous selected?
In one of my tables I store advertisement data, that’s one row per advertisement. I also store in an other table the prices for rental per dag, week, month, this table contain more than one row per advertisement.
I want to select al the rows from table 2 where there is a change in one of the prices (in the example row 1 and 3 in table 2) in the same query as the data selection. I know that I have to use a GROUP_CONCAT to get one row instead of a 2 row result in this case, but how to get 2 result rows from table 2 and 1 result row in total?
The outcome of the query has to be something like: tre,234,” 12345678911,12,45, 32555678911,12,67 ”
Table 1 (advertisements)
ID_adv data1 data2
1 tre 234
2 ghj 34
3 jk 098
4 jfjk 12
Table 2 (dates)
ID_dates ID_adv timestamp_day price1 price2
1 1 12345678911 12 45
2 1 22345677771 12 45
3 1 32555678911 12 67
4 2 42345671231 34 34
I tried
SELECT
t1.*,
GROUP_CONCAT(t2.date) AS dates
FROM Table1 t1
LEFT JOIN Table2 t2 ON t2.ID_adv = t1.ID_adv
WHERE t1.ID_adv = 3 GROUP BY t1.ID_adv

Can you try this one:
SELECT T3.ID_adv
, T3.data1
, T3.data2
, CAST(GROUP_CONCAT(CONCAT(T3.timestamp_day, ',', T3.price1, ',', T3.price2)) AS CHAR) AS DatePrice
FROM (
SELECT T1.*
, MIN(T2.timestamp_day) AS timestamp_day
, T2.price1
, T2.price2
FROM Table1 T1
LEFT JOIN Table2 T2 ON T2.ID_adv = T1.ID_adv
GROUP BY T1.ID_adv, T2.price1, T2.price2
) T3
GROUP BY T3.ID_adv;
I've tried it on SQL Fiddle.

Related

Make a tables join - if value in joining table is in multiple values in the second table

I have two tables which look like this:
ID
SOME_DATA_FIRST_TABLE
1
22
2
32
3
45
ID
SOME_DATA_SECOND_TABLE
1,2,3,4,5,6
99
5,6,7,8,9,11
31
56,67,88,45,11
87
How can I make a join between tables which would like:
SELECT *
FROM first_table as ft,
JOIN second_table as st,
on <if ft.ID (for example 1) is inside of the values in the column from the second table (for example 1,2,3,4,5,6) then it should make a join between tables.
How such a syntax should look like?
I couldn't find any similar thread, and couldn't find any solution to it.
It is better to normalize your data, the performance and database management would be better and easier.
As per the question you could use FIND_IN_SET:
select t1.ID,
t1.SOME_DATA_FIRST_TABLE,
t2.ID,
t2.SOME_DATA_SECOND_TABLE
from table1 t1
inner join table2 t2 ON FIND_IN_SET(t1.ID,t2.ID);
Result:
ID SOME_DATA_FIRST_TABLE ID SOME_DATA_SECOND_TABLE
1 22 1,2,3,4,5,6 99
2 32 1,2,3,4,5,6 99
3 45 1,2,3,4,5,6 99
Demo

How to get the output as following by combining data from 3 different tables

so I have 3 tables in my db, where all 3 tables contains a column which have similar data, but name of that column is different on all the 3 tables, below is an example.
Ban Table
user_id
ban_user_id
ban_date
reason
end_date
1300
1
xyz
xyz
xyz
32
1
xyz
xyz
xyz
43
2
xyz
xyz
xyz
Reports Table
user_id
last_modified_user_id
report_date
reason
end_date
1300
1
xyz
xyz
xyz
32
2
xyz
xyz
xyz
43
2
xyz
xyz
xyz
Warning Table
user_id
warning_user_id
warning_date
reason
end_date
1300
1
xyz
xyz
xyz
32
2
xyz
xyz
xyz
43
3
xyz
xyz
xyz
Now I want to fetch data by combining these 3 tables, where ban_user_id, last_modified_user_id, and warning_user_id contains the data of staff member who took the actions, so i want to group the data by the staff id.
The output i am looking for is as follows:
staff_id
total_reports
total_bans
total_warnings
1
1
2
1
2
2
1
1
3
0
0
1
where it is counting the data for each table by grouping the 2nd column, ban_user_id, last_modified_user_id, warning_user_id respectively. And than combining the data.
I tried things with UNION All and stuffs, but it didn't work out.
Thankyou in advance for your help
Use UNION ALL for all 3 tables and then aggregate:
SELECT staff_id,
COUNT(report) AS total_reports,
COUNT(ban) AS total_bans,
COUNT(warning) AS total_warnings
FROM (
SELECT last_modified_user_id AS staff_id, 1 AS report, null AS ban, null AS warning FROM Reports
UNION ALL
SELECT ban_user_id, null, 1, null FROM Ban
UNION ALL
SELECT warning_user_id, null, null, 1 FROM Warning
) t
GROUP BY staff_id;
Or:
SELECT staff_id,
SUM(report) AS total_reports,
SUM(ban) AS total_bans,
SUM(warning) AS total_warnings
FROM (
SELECT last_modified_user_id AS staff_id, 1 AS report, 0 AS ban, 0 AS warning FROM Reports
UNION ALL
SELECT ban_user_id, 0, 1, 0 FROM Ban
UNION ALL
SELECT warning_user_id, 0, 0, 1 FROM Warning
) t
GROUP BY staff_id;
See the demo.
You can use Table joins (Inner/outer/left/right) to get the data instead of union.
I'm assuming the staff_id is the equivalent of user_id column as you haven't mentioned anything about that, so your script will look something like this:
SELECT W.user_id AS staff_id,
B.ban_user_id,
R.last_modified_user_id,
W.warning_user_id
FROM Warning AS W
LEFT JOIN Reports AS R on R.user_id = W.user_id
LEFT JOIN Ban AS B on B.user_id = W.user_id
group by W.user_id

Select rows of table 1 when sum of colA grouped by ID is bigger than sum of colB in table 2 grouped by ID

We have a table of our sold items, it looks like this : ( Table A )
id
sell_id
item
amount
11
5
A
3000
12
5
B
2000
13
6
A
5120
14
7
C
5000
and a table where shipped items are placed that looks like this : ( Table B )
id
sub_id
item
amount
1
11
A
2850
2
11
A
150
3
12
B
2100
( Table B is matched to Table A by referencing TableA.id in Table B as sub_id ).
I want to find rows that sum of amount per TableA.id is not equivalent of sum of TableB.amount per TableB.sub_id.
In other words I want to know which sold items are not shipped exactly as the amount which is sold.
I've tried left joining tableA to tableB but i cannot get it to work.
Any help would be appreciated. Thanks!
For example:
SELECT a.*
FROM a
WHERE NOT EXISTS ( SELECT NULL
FROM b
WHERE a.id = b.sub_id
GROUP BY b.sub_id
HAVING a.amount = SUM(b.amount) )
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=1b13c67b6e622a5da72f63074d53d423

How to get the second last record per group? [duplicate]

This question already has answers here:
Get latest updated records
(5 answers)
Closed 5 years ago.
I have an table called DemoTable contains some fields like com_name, updated_date, demo_var, I queried on it like
select * from DemoTable where demo_var=100;
so for example here i got 1000 records. On this 1000 record i want to query to get the last updated row of com_name based on updated_date
My table looks like
id demo_var com_name updated_date
1 100 XYZ 2017-11-10
2 100 XYZ 2017-11-09
3 100 ABC 2017-10-10
4 100 ABC 2017-10-11
5 150 AJD 2017-11-11
First I want to fecth where demo_var=100 and get the different com_name which are last before updated ones.
For example like
2 100 XYZ 2017-11-09
3 100 ABC 2017-10-10
I want these two records to be fetched.
To achieve second latest row per group you can use following query
select a.*
from demo a
where a.demo_var = 100
and (
select count(*)
from demo b
where b.demo_var = 100
and a.com_name = b.com_name
and case when a.updated_date = b.updated_date
then a.id > b.id
else a.updated_date < b.updated_date
end
) = 1 /* here 1 is for second last , 0 for latest and so on */
Note it compare rows by updated_date so if there are 2 rows for same updated_date and com_name then i have used id column to pick the second latest row and is assume that id column is set to auto increment by default
Demo
Following query will work:
select t.demo_var,t.com_name,max(t.updated_date)
from
(
select demo_var,com_name,upddated_date
from DemoTable
where demo_var=100
and (com_name,updated_date) not in (select com_name,max(updated_date)
from DemoTable
where demo_var=100
group by demo_var,com_name
)
)t
group by t.demo_var,t.com_name;

MySQL Group by week num w/ multiple date column

I have a table with columns similar to below , but with about 30 date columns and 500+ records
id | forcast_date | actual_date
1 10/01/2013 12/01/2013
2 03/01/2013 06/01/2013
3 05/01/2013 05/01/2013
4 10/01/2013 09/01/2013
and what I need to do is get a query with output similar to
week_no | count_forcast | count_actual
1 4 6
2 5 7
3 2 1
etc
My query is
SELECT weekofyear(forcast_date) as week_num,
COUNT(forcast_date) AS count_forcast ,
COUNT(actual_date) AS count_actual
FROM
table
GROUP BY
week_num
but what I am getting is the forcast_date counts repeated in each column, i.e.
week_no | count_forcast | count_actual
1 4 4
2 5 5
3 2 2
Can any one please tell me the best way to formulate the query to get what I need??
Thanks
try:
SELECT weekofyear(forcast_date) AS week_forcast,
COUNT(forcast_date) AS count_forcast, t2.count_actual
FROM
t t1 LEFT JOIN (
SELECT weekofyear(actual_date) AS week_actual,
COUNT(forcast_date) AS count_actual
FROM t
GROUP BY weekOfYear(actual_date)
) AS t2 ON weekofyear(forcast_date)=week_actual
GROUP BY
weekofyear(forcast_date), t2.count_actual
sqlFiddle
You have to write about 30 (your date columns) left join, and the requirement is that your first date column shouldn'd have empty week (with a count of 0) or the joins will miss.
Try:
SELECT WeekInYear, ForecastCount, ActualCount
FROM ( SELECT A.WeekInYear, A.ForecastCount, B.ActualCount FROM (
SELECT weekofyear(forecast_date) as WeekInYear,
COUNT(forecast_date) as ForecastCount, 0 as ActualCount
FROM TableWeeks
GROUP BY weekofyear(forecast_date)
) A
INNER JOIN
( SELECT * FROM
(
SELECT weekofyear(forecast_date) as WeekInYear,
0 as ForecastCount, COUNT(actual_date) as ActualCount
FROM TableWeeks
GROUP BY weekofyear(actual_date)
) ActualTable ) B
ON A.WeekInYear = B.WeekInYear)
AllTable
GROUP BY WeekInYear;
Here's my Fiddle Demo
Just in case someone else comes along with the same question:
Instead of trying to use some amazing query, I ended up creating an array of date_columns_names and a loop in the program that was calling this query, and for each date_column_name, performing teh asme query. It is a bit slower, but it does work