how to select from database to show this new table into page. I'm just select from the same table. Can anyone help this?
Original Table from db
Id | Username | UserType | SpecialId
-------------------------------------
1 | jdoe | Type_A | SP_1
2 | dmatt | Type_A | SP_2
3 | kwill | Type_A | SP_3
4 | kwill_a | Type_B | SP_3
5 | dmatt_a | Type_B | SP_2
6 | dmatt_b | Type_B | SP_2
New table
No | Type_A Username | Type_B Username
-------------------------------------
1 | jdoe | -
2 | dmatt | dmatt_a, dmatt_b
3 | kwill | kwill_a
I think you may want to do this(Looks like a table pivot issue):
select
replace(SpecialId, 'SP_', '') as No,
max(case when UserType = 'Type_A' then UserName else '-' end) as Type_A_UserName,
max(case when UserType = 'Type_B' then UserName else '-' end) as Type_B_UserName
from (
select `UserType`, `SpecialId`, group_concat(UserName) as UserName
from yourtable
group by `UserType`, `SpecialId`) t
group by SpecialId
SqlFiddle Demo
Is this what you are looking for?
SELECT a.id, a.username, GROUP_CONCAT(b.username)
FROM (SELECT * FROM mytable WHERE usertype='Type_A') AS a
LEFT JOIN (SELECT * FROM mytable WHERE usertype='Type_B') AS b
ON a.specialid = b.specialid
This achieves the objective by combining a sub query with a self join.
SELECT
ifnull(tabA.UsernameA, '-') AS UsernameA,
ifnull(tabB.UsernameB, '-') AS UsernameB
FROM (
SELECT SpecialId, group_concat(Username) AS UsernameA
FROM tab
WHERE UserType = 'Type_A'
GROUP BY 1
) AS tabA
OUTER JOIN (
SELECT SpecialId, group_concat(Username) AS UsernameB
FROM tab
WHERE UserType = 'Type_B'
GROUP BY 1
) AS tabB ON tabA.SpecialId = tabB.SpecialId
Related
After the last update of Mailster (email marketing plugin for wordpress), they have changed the way they store the information about opens, clicks, unsubscribes...
Until now, everything was stored in two databases:
bao_posts: Like any other wordpress post, the information of the
email that is sent was there. (When the post_type = 'newsletter')
bao_mailster_actions: This is where the user's actions with the
email were stored. 1 when it was sent to a person, 2 when they
opened it, 3 when they clicked on it and 4 when they unsubscribed.
And with this query, I could get a table with all the emails and the information of their openings, clicks, unsubscribed...
SELECT bao_posts.post_modified,
bao_posts.ID,
bao_posts.post_title,
COUNT(CASE WHEN bao_mailster_actions.type = 1 then 1 ELSE NULL END) AS Number_People_Reached,
COUNT(CASE WHEN bao_mailster_actions.type = 2 then 1 ELSE NULL END) AS Opens,
COUNT(CASE WHEN bao_mailster_actions.type = 3 then 1 ELSE NULL END) AS Clicks,
COUNT(CASE WHEN bao_mailster_actions.type = 4 then 1 ELSE NULL END) AS Unsubs
FROM bao_posts
LEFT JOIN bao_mailster_actions ON bao_mailster_actions.campaign_id = bao_posts.ID
WHERE bao_posts.post_type = 'newsletter'
GROUP BY bao_posts.ID ;
*Expected result of this query at the end of the post.
Now the problem is that this setting is kept for emails before the update, but it has changed for new ones and now bao_mailster_actions is separated into:
bao_mailster_action_sent
bao_mailster_action_opens
bao_mailster_action_clicks
bao_mailster_action_unsubscribes
I know how to get the count of each of these tables like this:
SELECT bao_mailster_action_sent.campaign_id,
COUNT(bao_mailster_action_sent.count) AS Number_People_Reached
FROM bao_mailster_action_sent
GROUP BY bao_mailster_action_sent.campaign_id;
To get:
campaign_id
Number_People_Reached
9785
300
9786
305
(And so on with each of these 4 new tables).
So what I would like to do would be to join these 4 new queries to the original one. I've been trying to combine different JOINs, but I don't quite understand how to do it.
*Bearing in mind that if an email ID matches in both, I would need it to add up their clicks, opens (or whatever).
The expected outcome would be something like this (the same as the first query but with the aggregate data):
post_modified
ID
post_title
Number_People_Reached
Opens
Clicks
Unsubs
2021-04-29 13:13:03
9785
Prueba email
300
102
30
1
2021-04-30 15:12:01
9786
Segundo email
305
97
56
0
Thanks in advance!
I suggest that you use UNION ALL to join all the tables in a CTE.You can then use this in your query. I have modified the name because we cannot have to records with the same name.
> create table if not exists bao_mailster_action_sent
( campaign_id int,count int);
create table if not exists bao_mailster_action_opens
( campaign_id int,count int);
create table if not exists bao_mailster_action_clicks
( campaign_id int,count int);
create table if not exists bao_mailster_action_unsubscribes
( campaign_id int,count int);
CREATE TABLE if not exists bao_posts(
post_modified date,
ID int,
post_title varchar(50) );
insert into bao_mailster_action_sent values
(1,88),(2,4),(4,6);
insert into bao_mailster_action_opens values
(2,4),(3,5),(4,10);
insert into bao_mailster_action_clicks values
(1,3),(2,3),(4,6);
insert into bao_mailster_action_unsubscribes values
(1,4),(3,5),(4,5);
INSERT INTO bao_posts values
( '2021-03-01',1,'first post'),
( '2021-06-01',2,'second opion'),
( '2021-09-01',3,'third way'),
( '2021-12-01',4,'last post');
WITH bao_mailster_actionsent AS
( SELECT campaign_id,count, 1 type FROM
bao_mailster_action_sent
UNION ALL
SELECT campaign_id,count,2 FROM
bao_mailster_action_opens
UNION ALL
SELECT campaign_id,count,3 FROM
bao_mailster_action_clicks
UNION ALL
SELECT campaign_id,count,4 FROM
bao_mailster_action_unsubscribes)
SELECT bao_mailster_actionsent.campaign_id,
COUNT(bao_mailster_actionsent.count) AS TotalCount,
SUM(bao_mailster_actionsent.count) AS TotalNumber,
'type'
FROM bao_mailster_actionsent
GROUP BY bao_mailster_actionsent.campaign_id,'type' ;
WITH baoMailsterAction AS
( SELECT campaign_id,count, 1 type FROM
bao_mailster_action_sent
UNION ALL
SELECT campaign_id,count,2 FROM
bao_mailster_action_opens
UNION ALL
SELECT campaign_id,count,3 FROM
bao_mailster_action_clicks
UNION ALL
SELECT campaign_id,count,4 FROM
bao_mailster_action_unsubscribes)
SELECT bao_posts.post_modified,
bao_posts.ID,
bao_posts.post_title,
COUNT(CASE WHEN bao_mailster_actions.type = 1 then 1 ELSE NULL END) AS Number_People_Reached,
COUNT(CASE WHEN bao_mailster_actions.type = 2 then 1 ELSE NULL END) AS Opens,
COUNT(CASE WHEN bao_mailster_actions.type = 3 then 1 ELSE NULL END) AS Clicks,
COUNT(CASE WHEN bao_mailster_actions.type = 4 then 1 ELSE NULL END) AS Unsubs
FROM bao_posts
campaign_id | TotalCount | TotalNumber | type
----------: | ---------: | ----------: | ---:
1 | 1 | 88 | 1
2 | 1 | 4 | 1
4 | 1 | 6 | 1
2 | 1 | 4 | 2
3 | 1 | 5 | 2
4 | 1 | 10 | 2
1 | 1 | 3 | 3
2 | 1 | 3 | 3
4 | 1 | 6 | 3
1 | 1 | 4 | 4
3 | 1 | 5 | 4
4 | 1 | 5 | 4
post_modified | ID | post_title | Number_People_Reached | Opens | Clicks | Unsubs
:------------ | -: | :----------- | --------------------: | ----: | -----: | -----:
2021-03-01 | 1 | first post | 1 | 0 | 1 | 1
2021-06-01 | 2 | second opion | 1 | 1 | 1 | 0
2021-09-01 | 3 | third way | 0 | 1 | 0 | 1
2021-12-01 | 4 | last post | 1 | 1 | 1 | 1
db<>fiddle here
I finally got it to work using only the new tables that Mailster created (it seems that finally they did move all the info to the new tables with the update) and with 4 LEFT JOINS.
I leave the code in case someone else finds it useful:
SELECT P.post_modified,
P.ID,
P.post_title,
IFNULL(S.count,0) as 'Total',
IFNULL(O.count,0) as 'Aperturas',
IFNULL(C.count,0) as 'Clicks',
IFNULL(U.count,0) as 'Bajas' from bao_posts as P
LEFT JOIN (select campaign_id, count(DISTINCT subscriber_id) as count from bao_mailster_action_clicks group by campaign_id) as C ON C.campaign_id = P.ID
LEFT JOIN (select campaign_id, count(DISTINCT subscriber_id) as count from bao_mailster_action_opens group by campaign_id) as O ON O.campaign_id = P.ID
LEFT JOIN (select campaign_id, count(DISTINCT subscriber_id) as count from bao_mailster_action_sent group by campaign_id) as S ON S.campaign_id = P.ID
LEFT JOIN (select campaign_id, count(DISTINCT subscriber_id) as count from bao_mailster_action_unsubs group by campaign_id) as U ON U.campaign_id = P.ID
WHERE P.post_type = 'newsletter'
ORDER BY P.post_modified ASC ;
P.S: As I expected, Mailster's support has not helped at all :'(
I have table:
+----+-------+-------------+
| id | code | value_check |
| 1 | p-01 | OK |
| 2 | p-01 | NOT OK |
| 3 | p-01 | OK |
| 4 | p-02 | OK |
| 5 | p-02 | OK |
| 6 | p-02 | OK |
+----+-------+-------------+
How can I select record which having 'OK' group by code,but if there is one or more 'NOT OK' on value_check then don't need to select
expected result:
code
p-02
i have tried my query can get the result but its very slow
this is my query :
SELECT code FROM table
WHERE code
NOT IN (SELECT code FROM table
WHERE value_check = 'NOT OK' GROUP BY code)
GROUP BY code
any other solution?
Check whether the total count is equal to the count of rows having value as OK using HAVING clause.
Query
select `code` from `your_table_name`
group by `code`
having count(*) = sum(`value_check` = 'OK');
Find a demo here
Try below with conditional aggregation
select code from table
group by code
having sum(case when value_check='NOT OK' then 1 else 0 end)=0
You can try it also with correlated subquery:
demo
SELECT distinct code FROM cte1 a
WHERE NOT exists (SELECT 1 FROM cte1 b where a.code=b.code and val = 'NOT OK')
SELECT DISTINCT x.code
FROM my_table x
LEFT
JOIN my_table y
ON y.code = x.code
AND y.value_check = 'not ok'
WHERE x.value_check = 'ok'
AND y.id IS NULL
I want two display the result of the second table 'e_value', wich are two records (from only one column), as two columns for the select query from first table 'e_order_item'.
Also I am displaying many order items using a parameter 'collect_id',
so I want to display each two values of the table 'e_value' using to the order item id displayed on the select query.
for example, I have this on the tables
+-------------------------------+
| e_order_item |
+-------------------------------+
| oi_id oi_price oi_collect_id |
| 1 100 2 |
| 2 30 2 |
| 3 55 3 |
| 4 70 4 |
| 5 220 2 |
| 6 300 2 |
+-------------------------------+
+----------------------------+
| e_value |
+----------------------------+
| v_id v_value v_oi_id |
| 1 name1 1 |
| 2 surname1 1 |
| 3 name2 2 |
| 4 surname2 2 |
| 5 name3 5 |
| 6 surname3 5 |
+----------------------------+
I want to select the order_items that have collect_id = 2, and I want the result to be like this
+--------------------------------------------------+
| |
+--------------------------------------------------+
| Result |
| oi_id oi_price oi_collect_id name surname |
| 1 100 2 name1 surname1 |
| 2 30 2 name2 surname2 |
| 5 220 2 name3 surname3 |
| 6 300 2 null null |
| |
+--------------------------------------------------+
Here's the query:
SELECT
t.oi_id,
t.oi_price,
t.oi_collect_id,
LEFT (
GROUP_CONCAT(t.v_value),
IF (
LOCATE(',',GROUP_CONCAT(t.v_value)) = 0,
LENGTH(GROUP_CONCAT(t.v_value)),
LOCATE(',', GROUP_CONCAT(t.v_value)) - 1
)
) 'Name',
RIGHT (
GROUP_CONCAT(t.v_value),
LENGTH(GROUP_CONCAT(t.v_value)) -
IF (
LOCATE(',',GROUP_CONCAT(t.v_value)) = 0,
LENGTH(GROUP_CONCAT(t.v_value)),
LOCATE(',',GROUP_CONCAT(t.v_value))
)
) Surname
FROM
(
SELECT
*
FROM e_order_item
LEFT JOIN e_value ON e_order_item.oi_id = e_value.v_oi_id
WHERE e_order_item.oi_collect_id = 2
ORDER BY oi_id, v_id
) t
GROUP BY t.oi_id;
DEMO HERE
Note:
The following example illustrates how we can get the first string and second string from a comma separated string.
SET #str := 'A,BCDEFGHIJKL';
SELECT
LEFT(#str,IF(LOCATE(',',#str) = 0, LENGTH(#str),LOCATE(',',#str)-1)) AS StringBeforeComma,
RIGHT(#str,LENGTH(#str)-IF(LOCATE(',',#str)=0,LENGTH(#str),LOCATE(',',#str))) AS StringAfterComma
Result:
StringBeforeComma StringAfterComma
A BCDEFGHIJKL
You have to go for pivoting to get the desired result.
select oi_id, oi_price, oi_collect_id
, max(name) as name
, max(surname) as surname
from (
select
i.oi_id, i.oi_price, i.oi_collect_id
, case when #prevVal <> (#currVal:=v.v_oi_id)
then v.v_value
else null
end as name
, case when #prevVal = #currVal
then v.v_value
else null
end as surname
, #prevVal:=#currVal as temp_currVal
from e_order_item i
left join e_value v on v.v_oi_id = i.oi_id,
(select #prevVal:=-1, #currVal:=-1) as inits
where i.oi_collect_id=2
) as main_data
group by oi_id, oi_price, oi_collect_id
order by 1;
This is tested and run successfully...and give output as you want...
There are two subqueries:
1.First will give all result having collect_id = 2...
1.SELECT tab1.oi_id, tab1.oi_price, tab1.oi_collect_id
from(
SELECT oi_id, oi_price, oi_collect_id
from e_order_item
where oi_collect_id = 2
) as tab1;
2.This query will give you name, surname and id in different columns..
2.(SELECT e.v_value as name, surname, id
from (
select t1.v_value as surname, t1.v_oi_id as id from e_value as t1
group by t1.v_oi_id
)join e_value as e on id = e.v_oi_id and surname <> e.v_value
) as tab2 on tab1.oi_id = tab2.id;
Now left join these two query to get our desired result as:
SELECT tab1.oi_id, tab1.oi_price, tab1.oi_collect_id, name, surname
from(
SELECT oi_id, oi_price, oi_collect_id
from e_order_item
where oi_collect_id = 2
) as tab1 left join
(SELECT e.v_value as name, surname, id
from (
select t1.v_value as surname, t1.v_oi_id as id from e_value as t1
group by t1.v_oi_id
)join e_value as e on id = e.v_oi_id and surname <> e.v_value
) as tab2 on tab1.oi_id = tab2.id
order by tab1.oi_id asc; // to print in ascending order..
Why we use left join..You can use this link http://www.w3schools.com/sql/sql_join_left.asp to understand properly...
If this solution is helpful then let me know...
I have this table (test):
+----+---------+-----+---+
| ID | Name | A | B |
+----+---------+-----+---+
| 1 | Steve | 200 | 0 |
| 2 | Steve | 200 | 1 |
| 5 | James | 90 | 0 |
| 4 | James | 50 | 1 |
| 3 | Warrick | 100 | 1 |
+----+---------+-----+---+
and this SQL query:
SELECT one.Name as Name, one.A as one_value, zero.A as zero_value
FROM test one LEFT JOIN test zero ON one.Name = zero.Name AND one.A <> zero.A
WHERE zero.B = 0 AND one.B = 1
which returns:
+-------+-----------+------------+
| Name | one_value | zero_value |
+-------+-----------+------------+
| James | 50 | 90 |
+-------+-----------+------------+
But what I want is when a record exists only with B = 1 that it is included in the response with a NULL value or something in the zero_value column, like this:
+---------+-----------+------------+
| Name | one_value | zero_value |
+---------+-----------+------------+
| James | 50 | 90 |
| Warrick | 100 | NULL |
+---------+-----------+------------+
How can I do this?
Edit:
I worked it out:
SELECT one.Name, one.A, zero.A
FROM test one LEFT JOIN test zero ON one.Name = zero.Name AND ( zero.B = 0 OR zero.B is NULL )
WHERE ( one.A <> zero.A OR zero.A is null )
Because of the left join the value of zero.B may be NULL, so you need to extend the WHERE condition:
WHERE one.B=1 AND (zero.B IS NULL OR zero.B = 0)
Update
You should also move the score condition down into WHERE:
WHERE one.B=1 AND (zero.B IS NULL OR zero.B = 0)
AND (zero.A IS NULL OR one.A <> zero.A)
How about this
select Name ,
(case when B= 0 Then A else null) as zero_value,
(case when B= 1 Then A else null) as one_value
from test
LEFT JOIN is a good thing here, this is what you want :
SELECT
one.Name
,one.A as one_value
, zero.A as zero_value
FROM test one
LEFT JOIN test zero
on one.Name = zero.Name
and zero.B = 0
where one.B = 1
Perhaps you want to handle when record exists only with B = 0 that it is included in the response with a NULL value in the one_value column in same time :
SELECT
test.Name
, one.A as one_value
, zero.A as zero_value
FROM
( SELECT Name
FROM test
GROUP BY Name) test
LEFT JOIN test one
on test.Name = one.Name
and one.B = 1
LEFT JOIN test zero
on test.Name = zero.Name
and zero.B = 0
Here is a demo for both queries :)
http://www.sqlfiddle.com/#!2/6332a/7/0
Try thiz query that give exact result for u
SELECT Test.nme,
one.A AS one_value,
zero.A AS zero_value
FROM(SELECT name AS nme FROM test WHERE name NOT in( SELECT one.Name FROM test one LEFT JOIN test zero ON (one.Name = zero.Name AND one.A=zero.A)
WHERE zero.B=0 AND one.B=1)GROUP BY name)Test
LEFT JOIN test one ON test.nme=one.Name AND one.B=1
LEFT JOIN test zero ON test.nme=zero.Name AND zero.B=0;
I have tables as follows :
TABLE A
+-----+---------------+-------------+
| ID | DNR_DETAIL_ID | DESCRIPTION |
+-----+---------------+-------------+
| 1 | 1 | DESC A |
+-----+---------------+-------------+
| 2 | 2 | DESC B |
+-----+---------------+-------------+
| 3 | 3 | DESC C |
+-----+---------------+-------------+
TABLE B
+--------+---------------+
| DNR_ID | DNR_DETAIL_ID |
+------------------------+
| 1 | 1,2 |
+--------+---------------+
| 2 | 3 |
+--------+---------------+
As you can see, DNR_DETAIL_ID columns are common in both tables. What I want to do, left joining both tables with field values ( null or not )
THE RESULT SHOULD BE (IF DNR_ID = 1) :
+-------------+---------+
| DESCRIPTION | CHECKED |
+-------------+---------+
| DESC A | 1 |
+-------------+---------+
| DESC B | 1 |
+-------------+---------+
| DESC C | 0 |
+-------------+---------+
try this:
SELECT TA.description AS DESCRIPTION, CASE WHEN TB.checked IS NOT NULL THEN 1 ELSE 0 END AS CHECKED
FROM
(
select distinct description from TableA
) TA left join
(
SELECT description, 'checked' FROM TableA where dnt_detail_id in (
select dnr_detail_id from TableB where dnr_id = 1
)
)TB ON TB.description = TA.description
Try this using FIND_IN_SET()
SELECT
A.Description,
CASE WHEN B.DNR_ID IS NOT NULL THEN 1 ELSE 0 END as Checked
FROM A
LEFT JOIN B
ON FIND_IN_SET(A.DNR_DETAIL_ID, B.DNR_DETAIL_ID)
AND B.DNR_ID=1
SQLFiddle demo
SELECT a.DESCRIPTION,
CASE WHEN b.DNR_ID IS NOT NULL THEN 0 ELSE 1 END as CHECKED
FROM table_a a
LEFT JOIN table_b b
ON FIND_IN_SET(a.DNR_DETAIL_ID, b.DNR_DETAIL_ID)
Demo on sqlfiddle
Thank you so much guys. I have tried all of your suggestions but none of them work. Interesting thing is that code works well in sqlfiddle ( same schema and values ) but not working in local environment! Here is the query that working in local.
/**
* DNR_DETAIL_DESC IS TABLE A
* DNR_LIST IS TABLE B
*/
SELECT A.DNR_DETAIL_DESC,
CASE WHEN B.DNR_ID IS NOT NULL THEN 1 ELSE 0 END AS CHECKED
FROM MD_DNR_DETAIL A
LEFT JOIN (SELECT * FROM DNR_LIST WHERE DNR_ID = 1) AS B
ON FIND_IN_SET(A.DNR_DETAILT_ID, B.DNR_DETAIL_ID)
You can write it many ways, but here is the best way:
SELECT
MD_DNR_DETAIL.DNR_DETAIL_DESC as DESCRIPTION,
CASE WHEN DNR_LIST.DNR_ID IS NOT NULL THEN 1 ELSE 0 END AS CHECKED
FROM MD_DNR_DETAIL
LEFT JOIN DNR_LIST
ON FIND_IN_SET(MD_DNR_DETAIL.DNR_DETAILT_ID, DNR_LIST.DNR_DETAIL_ID)