Combine mysql result into 1 row - php

table img
SELECT namaline, shift1 FROM semualine WHERE cektelatshift1 <> 'Ontime' UNION
SELECT namaline, shift2 FROM semualine WHERE cektelatshift2 <> 'Ontime' UNION
SELECT namaline, shift3 FROM semualine WHERE cektelatshift3 <> 'Ontime';
namaline
shift1
Line 1
Shift 1
Line 2
Shift 1
Line 3
Shift 1
Line 1
Shift 2
Line 2
Shift 2
Line 3
Shift 2
Line 1
Shift 3
Line 2
Shift 3
I want to combine all this result into 1 cell
myexpectation is
1 cell
Line 1 Shift 1, Line 2 Shift 1, Line 3 Shift 1, Line 1 Shift 2, Line 1 Shift 1, Line 2 Shift 2, Line 1 Shift 3, Line 2 Shift 3

Thank for all the answer.
Sorry, I'm still new here should show my DB and used english. I figure out the close answer.
SELECT shift1 AS shift, GROUP_CONCAT(`namaline` SEPARATOR ', ') AS 'line'
FROM semualine
WHERE cektelatshift1 <> 'Ontime'
UNION
SELECT shift2 AS shift, GROUP_CONCAT(`namaline` SEPARATOR ', ') AS 'line'
FROM semualine
WHERE cektelatshift2 <> 'Ontime'
UNION
SELECT shift3 AS shift, GROUP_CONCAT(`namaline` SEPARATOR ', ') AS 'line'
FROM semualine
WHERE cektelatshift3 <> 'Ontime';
shift
line
Shift 1
Line 1, Line 2, Line 3
Shift 2
Line 1, Line 2, Line 3
Shift 3
Line 1, Line 2

To achieve the output format you are looking for the following needs to be done
select GROUP_CONCAT(namaline, ' ', shift1) from semualine;
In GROUP_CONCAT space is needed between columns to have the space in the output as well

The repeating pattern shift1, cektelatshift1, shift2, cektelatshift2, ... is a good indication of a table that would benefit from being normalized.
Both of these queries provide a result similar to your example (cannot be the same as your example is inconsistent). They differ in whether it is the row or column which is concatenated first.
SELECT
GROUP_CONCAT(
CONCAT_WS(', ',
IF(cektelatshift1 <> 'Ontime', CONCAT_WS(' ', namaline, shift1), NULL),
IF(cektelatshift2 <> 'Ontime', CONCAT_WS(' ', namaline, shift2), NULL),
IF(cektelatshift3 <> 'Ontime', CONCAT_WS(' ', namaline, shift3), NULL)
)
SEPARATOR ', '
)
FROM semualine
WHERE NOT (cektelatshift1 = 'Ontime' AND cektelatshift2 = 'Ontime' AND cektelatshift3 = 'Ontime');
SELECT
CONCAT_WS(', ',
GROUP_CONCAT(
IF(cektelatshift1 <> 'Ontime', CONCAT_WS(' ', namaline, shift1), NULL)
SEPARATOR ', '
),
GROUP_CONCAT(
IF(cektelatshift2 <> 'Ontime', CONCAT_WS(' ', namaline, shift2), NULL)
SEPARATOR ', '
),
GROUP_CONCAT(
IF(cektelatshift3 <> 'Ontime', CONCAT_WS(' ', namaline, shift3), NULL)
SEPARATOR ', '
)
)
FROM semualine
WHERE NOT (cektelatshift1 = 'Ontime' AND cektelatshift2 = 'Ontime' AND cektelatshift3 = 'Ontime');

Related

Mysql query for displaying row value as column header dynamically

my table looks ike this
dt ticker open
1 A 1.2
1 B 6
2 A 1.4
2 B 6.5
I would like it to turn out to be
dt A B
1 1.2 1.4
2 6 6.5
I tried using mysql query in below format
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(ticker= ''',
ticker,
''', open, NULL)) AS ',
ticker
)
) INTO #sql
FROM properties;
SET #sql = CONCAT('SELECT dt, ', #sql, ' FROM properties GROUP BY dt');
while executing the query in phpmyadmin I am getting below error .
Warning in .\libraries\dbi\DBIMysqli.php#436
mysqli_fetch_fields() expects parameter 1 to be mysqli_result, boolean given
can anyone help me with this ?

Rows Into Columns Queries MySql

I have this table:
ID CODE WEEK SEX
1 abc 1 F
2 abc 2 M
3 xyz 3 F
4 abc 1 M
and I am using this query to filter the data:
SELECT `code`,`week`,`sex`, COUNT(`week`) as cnt
FROM `table`
WHERE `code` = "abc"
and `sex` = "F"
group by `week`
having (`week` > 0)
UNION ALL
SELECT `code`,`week`,`sex`, COUNT(`week`) as cnt
FROM `table`
WHERE `code` = "abc"
and `sex` = "M"
group by `week`
having (`week` > 0)
and this is the result:
CODE WEEK SEX cnt
abc 1 F 1
abc 1 M 1
abc 2 M 1
But now I need to show the data in this way:
CODE WEEK M F
abc 1 1 1
abc 2 1 0
So I have this query:
SELECT
`WEEK`,`CODE`,
GROUP_CONCAT(if(`SEX` = "F", `cnt`, NULL)) AS "F",
GROUP_CONCAT(if(`SEX` = "M", `cnt`, NULL)) AS "M"
FROM `temp_table`
GROUP BY `WEEK`
ORDER BY CAST(`WEEK` AS UNSIGNED)
How can I combine this 2 queries? Is there a better way to do this?
SELECT `WEEK`,`CODE`
, SUM(IF(`SEX` = "F", cnt, 0)) AS `F`
, SUM(IF(`SEX` = "M", cnt, 0)) AS `M`
FROM `table`
GROUP BY `WEEK`,`CODE`
;
I'm not sure why you were doing that strange ORDER BY, and I was pretty sure you would want to group on CODE as well. (Edit: Yes, the CAST was appropriate for the data type of week.)
If using the first query as the "source", see below:
SELECT `WEEK`,`CODE`
, SUM(IF(`SEX` = "F", 1, 0)) AS `F`
, SUM(IF(`SEX` = "M", 1, 0)) AS `M`
FROM ([original query goes in here]) `subQ`
GROUP BY `WEEK`,`CODE`
;

Use SQL to find out the highest frequency of the most common word

I am using MySQL Workbench for my application (consisting of JavaScript and PHP). I have a SQL database that contains the tweets. I would like to query what is the highest frequency of the word from the tweets(sentence). I have done research that says to use count() to query but I still unable to get what I want.
Example dataset:
tweetsID | Tweets | DateTime
1 | I can't wait to go to school tomorrow! | 2014-07-18 12:00:00
2 | My teacher saw me hanging out after school | 2014-07-18 12:20:00
3 | I had Pepper Lunch for my dinner | 2014-07-18 12:30:00
4 | Something happened in my school omg | 2014-07-18 12:40:00
5 | This project is so hard! | 2014-07-18 12:50:00
Expected output:
Words |frequency
I |2
can't |1
wait |1
to |2
school |3
tomorrow|1
! |2
my |3
had |1
teacher |1
saw |1
me |1
hanging |1
out |1
after |1
pepper |1
lunch |1
for |1
dinner |1
something|1
happened |1
in |1
omg |1
this |1
project |1
is |1
so |1
hard |1
I have create the sample data in the following link :
[ http://sqlfiddle.com/#!2/3b3f2/1 ]
Anyone can teach me or any reference for me to guide? Thank you in advance.
I think your best bet is to do this in PHP. array_count_values() comes to mind.
Try this:
$sqlresults = array(
"I can't wait to go to school tomorrow!",
"My teacher saw me hanging out after school",
"I had Pepper Lunch for my dinner",
"Something happened in my school omg",
"This project is so hard!"
);
$arr = array();
foreach ($sqlresults as $str) {
$arr = array_merge($arr, explode(' ', $str));
}
$arr = array_count_values($arr);
print_r($arr);
See demo
References:
array_count_values()
array_merge()
explode()
I would say you need to refactor your DB.
I would introduce a separate table - words (id, word) and a relation table tweet_to_word (tweet_id, word_id, word_count) where you can keep all words for each tweet.
After that it would be a simple
select count(ttw.word_count)
from tweet_to_word ttw
group by word_id
you can add ORDER BY to the select to find the most popular word
As a demonstration of how messy this could get, the following will almost do what you want in a single piece of SQL.
This firstly replace punctuation with spaces, then replaces 2 spaces with 1 space (several times). The idea of this is to give you a string which contains the words separated by a single space.
From this the number of words is calculated by comparing the length with the length with spaces replaced with nothing.
This is then cross joined with selects getting the numbers 0 to 9, which when cross joined gives you 1000 rows for each tweet, along with the numbers 0 to 999. This is then used with SUBSTRING_INDEX to get all the individual words. The number (from 0 to 999) is compared with the number of words in the tweet to avoid duplicating the last word.
Then this is just used for a normal COUNT / GROUP BY to get the word and count.
SELECT Words, COUNT(*) AS frequency
FROM
(
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(Tweets, ' ', 1 + units.i + tens.i * 10 + hundreds.i * 100), ' ', -1) AS Words
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
CROSS JOIN
(
SELECT Tweets,
(LENGTH(Tweets) - LENGTH(REPLACE(Tweets, ' ', ''))) + 1 AS Tweets_Words
FROM
(
SELECT TRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(Tweets, '(', ' '), ')', ' '), ',', ' '), '.', ' '), ';', ' '), ':', ' '), '?', ' '), '!', ' '), '{', ' '), '}', ' '), ' ', ' '), ' ', ' '), ' ', ' '), ' ', ' ')) AS Tweets
FROM some_tweets
) sub0
) sub1
WHERE Tweets_Words > (units.i + tens.i * 10 + hundreds.i * 100)
) sub2
GROUP BY Words
The replacement of double spaces with a single space can probably be removed, replacing it with a check that the resulting word is not '':-
SELECT Words, COUNT(*) AS frequency
FROM
(
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(Tweets, ' ', 1 + units.i + tens.i * 10 + hundreds.i * 100), ' ', -1) AS Words
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
CROSS JOIN
(
SELECT Tweets,
(LENGTH(Tweets) - LENGTH(REPLACE(Tweets, ' ', ''))) + 1 AS Tweets_Words
FROM
(
SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(Tweets, '(', ' '), ')', ' '), ',', ' '), '.', ' '), ';', ' '), ':', ' '), '?', ' '), '!', ' '), '{', ' '), '}', ' ') AS Tweets
FROM some_tweets
) sub0
) sub1
WHERE Tweets_Words > (units.i + tens.i * 10 + hundreds.i * 100)
) sub2
WHERE Words != ''
GROUP BY Words
SQL fiddle for it here:-
http://www.sqlfiddle.com/#!2/f28e5/1

How to display multiple row values into single row

Here my table is like this
Leave_Type Leave_Balance
CL 12
PL 10
Now i want to display my data like below
Leave_Type_CL Leave_Type_PL Leave_Balance_CL Leave_Balance_PL
CL PL 12 10
Try this:
SELECT CONCAT(
group_concat(CONVERT(Leave_Type, CHAR(2)) separator ' '),
' ',
group_concat(CONVERT(Leave_Balance, CHAR(2)) separator ' ')
) FROM Leave_Table;

SELECT id where min or max value from multiple columns

I'm looking for a fast MySQL query that returns the id of the product with the lowest (min) or highest (max) price, compared to all price categories (a, b, c and d).
I have a product table called chocolate_stock with several price categories. It's pretty easy to receive the lowest (min) or highest (max) price from a specific category (a or b or c or d).
id | name | price_a | price_b | price_c | price_d |
--------------------------------------------------------------
1 | Chips Ahoy | 250 | 530 | 720 | 120
--------------------------------------------------------------
2 | Chocolate Chunk | 250 | 90 | 32.92 | 110
--------------------------------------------------------------
3 | Oreo | 103 | 44.52 | 250 | 850
--------------------------------------------------------------
The price categories are decimal(10,2). Here's a sample that returns the highest price from the categories, but not the id:
$t = 'chocolate_stock';
$arrIds = array(1, 3);
$strQuery = "SELECT id,
MAX(price_a) AS price_a,
MAX(price_b) AS price_b,
MAX(price_c) AS price_c,
MAX(price_d) AS price_d
FROM $t WHERE id IN(". implode(',', array_map('intval', $arrIds)) .")";
What is the fastest way to retrieve this information?
This query does what you want:
(select t.*
from $t t
where . . .
order by price_a desc
limit 1) union all
(select t.*
from $t t
where . . .
order by price_b desc
limit 1) union all
(select t.*
from $t t
where . . .
order by price_c desc
limit 1) union all
(select t.*
from $t t
where . . .
order by price_d desc
limit 1)
If you have an index on id it should perform reasonably well.
That approach requires four passes through the table (although the index on id should greatly reduce that). The following approach requires only one pass through the table:
select MAX(price_a),
substring_index(group_concat(id order by price_a desc), ',', 1),
max(price_b),
substring_index(group_concat(id order by price_b desc), ',', 1),
max(price_c),
substring_index(group_concat(id order by price_c desc), ',', 1),
max(price_d),
substring_index(group_concat(id order by price_d desc), ',', 1)
from $t
where . . .
It uses a trick with group_concat() and substring_index() to get the max id for each of the columns.
It might help if you were to tabulate what you want your output to look like, but I think the piece you are missing is the HAVING clause.
first - try this
select min(id), max(price_a) from $t having price_a = max(price_a)
Then try
select min(id), min(price_a) from $t having price_a = min(price_a)
union
select min(id), max(price_a) from $t having price_a = max(price_a)
The first thing you would want to do is normalise your data, for ease of later querying I would create the following view:
CREATE VIEW NormalT
AS
SELECT ID, Name, 'Price_a' AS Type, Price_a AS Price
FROM T
UNION ALL
SELECT ID, Name, 'Price_b' AS Type, Price_b AS Price
FROM T
UNION ALL
SELECT ID, Name, 'Price_c' AS Type, Price_c AS Price
FROM T
UNION ALL
SELECT ID, Name, 'Price_d' AS Type, Price_d AS Price
FROM T;
Then I am not sure of the format you want, if you want the min an max for each price you could use this:
SELECT mt.Type2,
mt.Type,
mt.Price,
t.ID,
t.Name
FROM ( SELECT Type, MIN(Price) AS Price, 'MIN' AS Type2
FROM NormalT
GROUP BY Type
UNION ALL
SELECT Type, MAX(Price) AS Price, 'MAX' AS Type2
FROM NormalT
GROUP BY Type
) mt
INNER JOIN NormalT T
ON mt.Type = T.Type
AND mt.Price = t.Price
ORDER BY mt.Type2, mt.Type, t.ID;
Which will output the following from your sample data:
TYPE2 TYPE PRICE ID NAME
MAX Price_a 250 1 Chips Ahoy
MAX Price_a 250 2 Chocolate Chunk
MAX Price_b 530 1 Chips Ahoy
MAX Price_c 720 1 Chips Ahoy
MAX Price_d 850 3 Oreo
MIN Price_a 103 3 Oreo
MIN Price_b 44.52 3 Oreo
MIN Price_c 32.92 2 Chocolate Chunk
MIN Price_d 110 2 Chocolate Chunk
However, if it is just the min and max of all prices (a, b, c and d) then you could use this:
SELECT mt.Type2,
t.Type,
mt.Price,
t.ID,
t.Name
FROM ( SELECT MIN(Price) AS Price, 'MIN' AS Type2
FROM NormalT
UNION ALL
SELECT MAX(Price) AS Price, 'MAX' AS Type2
FROM NormalT
) mt
INNER JOIN NormalT T
ON mt.Price = t.Price;
Which will output this:
TYPE2 TYPE PRICE ID NAME
MIN Price_c 32.92 2 Chocolate Chunk
MAX Price_d 850 3 Oreo
Examples on SQL Fiddle
Try this , It's emulating Analytics as MYSQL doesn't have them by default :
SELECT id,
( select MAX(price_a) from $t t2 where t2.id = t1.id ) AS price_a,
( select MAX(price_b) from $t t2 where t2.id = t1.id ) AS price_b,
( select MAX(price_c) from $t t2 where t2.id = t1.id ) AS price_c,
( select MAX(price_d) from $t t2 where t2.id = t1.id ) AS price_d
FROM $t t1 WHERE id IN(". implode(',', array_map('intval', $arrIds)) .")
Source From : http://www.oreillynet.com/pub/a/mysql/2007/03/29/emulating-analytic-aka-ranking-functions-with-mysql.html?page=3
You are not getting id because, MAX returns one value. But it is not so with id.You can use seperate queries like
SELECT id,MAX(price_a) FROM $t WHERE id IN (". implode(',', array_map('intval', $arrIds)).")";
SELECT id,MAX(price_b) FROM $t WHERE id IN (". implode(',', array_map('intval', $arrIds)).")";
etc

Categories