Group_concat distint on selected columns in mysql - mysql

I have a table apartment as below
aid | aname
1 | dream home
2 | My hub
3 | Lake view
another table apartment_details
id | aid | bhk | size | facing
1 | 1 | 2 | 1200 | east
2 | 1 | 2 | 1200 | west
3 | 1 | 2 | 1000 | south
4 | 1 | 2 | 1000 | north
I have written the query as
SELECT distinct ap.aid, ap.aname, al.bhk, (select group_concat(distinct concat(al.bhk,'BHK - ',al.size)) from apartment_details as al where al.id = ap.aid) as details
When I tried to display details using foreach I get the output as
2BHK - 1200
2BHK - 1200
2BHK - 1000
2BHK - 1000
In this query it is considering bhk, size, facing in distinct and the output obtained is based on facing. This looks something like I am displaying duplicate data or something the same data is repeating as there is no facing displayed. How can I display only distinct values based on bhk, size and not facing so that I get the output as
2BHK - 1200
2BHK - 1000
Can anyone help me in solving this issue? Thanks in advance

To my way of thinking, in general, there is no problem in SQL for which GROUP_CONCAT is the solution. So, with that in mind, let's start with this:
SELECT DISTINCT bhk,size FROM apartment_details

Related

Get clan with bigger kills/deaths coef

I got table:
id | nick | clanid | kills | deaths | map
1 | xdd | 2 | 123 | 23 | 'map_1'
2 | xd | 1 | 23 | 32 | 'map_1'
this table continuing with similar records. I need to get only 1 result, it's should be clanid and coef(kills/deaths), of course i need the clan with higher coef. This table got many records with players which have different clanids, kills, deaths and map.
The complete result i need: it's clanid with higher coef at current map.I tried SQL like that:
SELECT `clanid`, SUM(kills)/SUM(deaths) as 'coef'
FROM `test_user_stats`
WHERE `map`='map_1'
But that returs only 1 record with last clanid and his coef.
What i have to do next?(i obviously need to use LIMIT 1 and ORDER BY coef, but i got problems even without going so far).

Detecting variations in a data set

I have a data set with this structure:
ContractNumber | MonthlyPayment | Duration | StartDate | EndDate
One contract number can occur many times as this data set is a consolidation of different reports with the same structure.
Now I want to filter / find the contract numbers in which MonthlyPayment and/or Duration and/or StartDate and/or EndDate differ.
Example (note that Contract Number is not a Primary key):
ContractNumber | MonthlyPayment | Duration | StartDate | EndDate
001 | 500 | 12 | 01.01.2015 | 31.12.2015
001 | 500 | 12 | 01.01.2015 | 31.12.2015
001 | 500 | 12 | 01.01.2015 | 31.12.2015
002 | 1500 | 24 | 01.01.2014 | 31.12.2017
002 | 1500 | 24 | 01.01.2014 | 31.12.2017
002 | 1500 | 24 | 01.01.2014 | 31.12.2018
With this sample data set, I would need to retrieve 002 with a specific query. 001 is the the same and does not Change, but 002 changes over time.
Besides of writing a VBA script running over an Excel, I don't have any solid idea on how to solve this with SQL
My first idea would be a SQL Approach with grouping, where same values are grouped together, but not the different ones. I am currently experimenting on this one. My attempt is currently:
1.) Have the usual table
2.) Create a second table / query with this structure:
ContractNumber | AVG(MonthlyPayment) | AVG(Duration) | AVG(StartDate) | AVG(EndDate)
Which I created with Grouping.
E.G.
Table 1.)
ContractNumber | MonthlyPayment
1 | 10
1 | 10
1 | 20
2 | 300
2 | 300
2 | 300
Table 2.)
ContractNumber | AVG(MonthlyPayment)
1 | 13.3
2 | 300
3) Now I want to find the distinct contract number where - in this example only the MonthlyPayment - does not equal to the average (it should be the same - otherwise we have a variation which I need to find).
Do you have any idea how I could solve this? I would otherwise start writing a VBA or Python script. I have the data set in CSV, so for now I could also do it with MySQL, Power Bi or Excel.
I need to perform this Analysis once, so I would not Need a full approach, so the queries can be splitted into different steps.
Very appreciated! Thank you very much.
To find all contract numbers with differences, use:
select ContractNumber
from
(
select distinct ContractNumber, MonthlyPayment , Duration , StartDate , EndDate
from MyTable
) x
group by ContractNumber
having count(*) >1

Best way to gain performance and do fast sql queries?

I use MySQL for my database and i do some processing on the database side to make it easier for my application.
The queries i do used to be very fast until recently my database has lots of data and the queries are very very very slow.
My application do mainly statistics and has lots of related database to fetch data.
Here is an example:
tbl_game
+-------------------------------------+
| id | winner | duration| endedAt |
|--------+--------+---------+---------|
| 1 | 1 | 1200 |timestamp|
| 2 | 0 | 1200 |timestamp|
| 3 | 1 | 1200 |timestamp|
| 4 | 1 | 1200 |timestamp|
+-------------------------------------+
winner is either 0 or 1 for the team who won the game
duration is the number of seconds a game took
tbl_game_player
+-------------------------------------------------+
| gameId | playerId | playerSlot | frags | deaths |
|--------+----------+------------+-------+--------|
| 1 | 100 | 1 | 24 | 50 |
| 1 | 150 | 2 | 32 | 52 |
| 1 | 101 | 3 | 26 | 62 |
| 1 | 109 | 4 | 48 | 13 |
| 1 | 123 | 5 | 24 | 52 |
| 1 | 135 | 6 | 30 | 30 |
| 1 | 166 | 7 | 28 | 48 |
| 1 | 178 | 8 | 52 | 96 |
| 1 | 190 | 9 | 12 | 75 |
| 1 | 106 | 10 | 68 | 25 |
+-------------------------------------------------+
The details are only for the first game with id 1
1 game has 10 player slots where slot 1-5 = team 0 and 6-10 = team 1
There are more details in my real table this is just to give an overview.
So i need to calculate the statistics of each player in all the games. I created a view to accomplish this and it works fine when i have little data.
Here is an example:
+--------------------------------------------------------------------------+
| gameId | playerId | frags | deaths | actions | team | percent | isWinner |
|--------+----------+-------+--------+---------+------+---------+----------|
actions = frags + deaths
percent = (actions / sum(actions of players in the same team)) * 100
team is calculated using playerSlot in 1,2,3,4,5 or 6,7,8,9,10
isWinner is calculated by the team and winner
This is just 1 algorithm and i have many others to perform. My database is 1 milion + records and the queries are very slow.
here is the query for the above:
SELECT
tgp.gameId,
tgp.playerId,
tgp.frags,
tgp.deaths,
tgp.frags + tgp.deaths AS actions,
IF(playerSlot in (1,2,3,4,5), 0, 1) AS team,
((SELECT actions) / tgpx.totalActions) * 100 AS percent,
IF((SELECT team) = tg.winner, 1, 0) AS isWinner
FROM tbl_game_player tgp
INNER JOIN tbl_game tg on tgp.gameId = tg.id
INNER JOIN (
SELECT
gameId,
SUM(frags) AS totalFrags,
SUM(deaths) AS totalDeaths,
SUM(frags) + SUM(deaths) as totalActions,
IF(playerSlot in (1,2,3,4,5), 0, 1) as team
FROM tbl_game_player
GROUP BY gameId, team
) tgpx on tgp.gameId = tgpx.gameId and team = tgpx.team
It's quite obvious that indexes don't help you here¹, because you want all data from the two tables. You even want the data from tbl_game_player twice, once aggregated, once not aggregated. So there are millions of records to read and join. Your query is fine, and I see no way to improve it really.
¹ Of course you should always have indexes on primary and foreign keys, so the DBMS can make use of them in joins. (E.g. there should be an index on tbl_game(tgp.gameId)).
So your options lie outside the query:
Hardware (obviously).
Add a computed column for the team to tbl_game_player, so at least you save its evaluation when querying.
Partitions. One partition per team, so the aggregates can be calcualted separately.
Pre-computed data: Add a table tbl_game_team holding the sums; fill it with triggers. Thus you don't have to compute the aggregates in your query.
Data warehouse table: Make a table holding the complete result. Fill it with triggers or at intervals.
Setting up indexes would speed up your queries. Queries can take a while to run if there is a lot of results, this is definitely a start though.
for large databases Mysql INDEX can be very helpful in speed problems, An index can be created in a table to find data more quickly & efficiently. so must create index , you can learn more about MYsql index here http://www.w3schools.com/sql/sql_create_index.asp

Joining two column's components into a single column based on criteria

I have below data set and I want to have it joined into a single column like below from two different columns. Here is the data set.
Actual Data set:
Station_id |Market | Households | Over Air
1 |Houston |2117641 |220221
2 |Topeka |182443 |4562
3 |Columbus |922291 |167671
3 |Boston |1200 |13400
From the above data set I want to have below result.
Station_id | Market | Value
1 | Houston | 2117641
2 | Topeka | 182443
3 | Columbus | 167671
3 | Boston | 13400
please help me how to write the query to get the result. I am using Mysql database.
Thanks & Regards
Arfater Rahman.
Please try using the following query:
SELECT Station_id, Market,
CASE
WHEN Station_id=1 THEN Households
WHEN Station_id=2 THEN Households
WHEN Station_id=3 THEN Over_Air
END AS Value
FROM DATASET
Is this what you want?
CASE
WHEN Station_id = 3 then `Over Air`
ELSE `Households`
END
based on:
Station_id | Market | Households | Over Air
1 Houston 2117641 220221
2 Topeka 182443 4562
3 Columbus 922291 167671
3 Boston 1200 13400

Completing a MAX() but using data from a few more tables

well I eventually got to a max() on one table pulling correctly using max() - took me sometime to understand what was going on and reading the limits of mysql when using it
I have spent a some time doing some demo data on sqlfiddle (one below is with just the max on the one table
http://sqlfiddle.com/#!2/fff224/1
what i would like (and to absorb as ive tried for the last 2 hours on getting this to work) is how to incorporate another tables that dont need to use max (i have included these in the sqlfiddle
the result i would be after would be
case_number full_address case owner client compiled date(max()) recommendation
1000 1 high street bob london 14/12/2012 let
1001 2 high street ken Compton 13/12/2013 sell
1002 3 high street ken Leeds 14/12/2013 sell
completing the inner joins between from client\staff\ to case process im fine with its just this nested select max im falling over on
SELECT p.case_number
, p.full_address
, s.case_owner_name 'case owner'
, c.client_name client
, r.compiled_date
, r.recommendation
FROM case_process p
JOIN staff s
ON s.case_owner_number = p.case_owner_number
JOIN client c
ON c.client_number = p.client_number
JOIN reporting r
ON r.case_number = p.case_number
JOIN (SELECT case_number,MAX(compiled_date) max_compiled_date FROM reporting GROUP BY case_number) x
ON x.case_number = r.case_number
AND x.max_compiled_date = r.compiled_date;
+-------------+---------------+------------+---------+---------------+----------------+
| case_number | full_address | case owner | client | compiled_date | recommendation |
+-------------+---------------+------------+---------+---------------+----------------+
| 1000 | 1 high street | Bob | London | 2012-12-14 | let |
| 1001 | 2 high street | Ken | Compton | 2013-12-13 | sell |
| 1002 | 3 high street | Ken | Leeds | 2012-12-14 | sell |
+-------------+---------------+------------+---------+---------------+----------------+
3 rows in set (0.00 sec)
fiddle of same... http://sqlfiddle.com/#!2/fff224/7