Trying to get multiple results with nested select statements - php

I'm trying to get this statement to return multiple rows (one for each campaign ID). This code was originally intended for only accepting one campaign ID, but I'm needing to involve it to accepting multiple campaign IDs. The following code snippet only returns 1 row, but should be returning 6 rows. I'd also assume this statement could be more efficient.
SELECT * FROM
(SELECT
campaignID,
count(ctaS.engagementID) AS numEngagements,
count(distinct(ctaS.targetID)) AS numTargets,
SUM(engagementType='email') AS numEmails,
SUM(engagementType='call') as numCalls,
SUM(engagementType='meeting') as numMeetings,
count(distinct(ctaC.email)) AS numEngagementsByEmail,
count(distinct(ctaS.ipAddress)) AS numEngagementsByIP
FROM engagements AS ctaS
LEFT JOIN engagements_content AS ctaC ON ctaS.engagementID = ctaC.engagementID
WHERE ctaS.campaignID IN ('639ba3c9d86726f2ef5a6ca3','2bce996549ed7acb','f91491361140ccd81a7ab8bb','3d4d9a45bba4b8ef9c22edbc','VhFfwsAnxr9OBfRvGWKsyr7H','0819c9ff210c24f9efcb16fc')
AND ctaS.is_active = 1
AND ctaS.targetID <> ''
AND ctaS.engagementType <> ''
AND ctaS.ipAddress NOT IN ('75.43.48.211')
) as tbl1,
(SELECT
t1.numTimesIndexLoaded,
t1.numTimesIndexLoadedUnique,
t1.numTimesResultsLoaded,
t1.numTimesResultsLoadedUnique,
t1.numTimesCTALoaded,
t1.numTimesCTALoadedUnique
FROM
(SELECT sum(ctaSL.page = 'index') AS numTimesIndexLoaded,
sum(ctaSL.page = 'results') AS numTimesResultsLoaded,
sum(ctaSL.page = 'cta') AS numTimesCTALoaded,
count(DISTINCT CASE WHEN ctaSL.page = 'index' THEN ctaSL.ip_address END) AS numTimesIndexLoadedUnique,
count(DISTINCT CASE WHEN ctaSL.page = 'results' THEN ctaSL.ip_address END) AS numTimesResultsLoadedUnique,
count(DISTINCT CASE WHEN ctaSL.page = 'cta' THEN ctaSL.ip_address END) AS numTimesCTALoadedUnique
FROM stats_page_loads AS ctaSL
WHERE ctaSL.campaign_id IN ('639ba3c9d86726f2ef5a6ca3','2bce996549ed7acb','f91491361140ccd81a7ab8bb','3d4d9a45bba4b8ef9c22edbc','VhFfwsAnxr9OBfRvGWKsyr7H','0819c9ff210c24f9efcb16fc')
AND ctaSL.is_active = 1
AND ctaSL.ip_address NOT IN ('75.43.48.211')
) t1
) as tbl2,
(SELECT tblA.numFacebookClicks, tblB.numTwitterClicks
FROM
(SELECT count(target_id) AS numFacebookClicks
FROM stats_social_clicks AS sc
WHERE sc.social_network = 'facebook'
AND sc.campaign_id IN ('639ba3c9d86726f2ef5a6ca3','2bce996549ed7acb','f91491361140ccd81a7ab8bb','3d4d9a45bba4b8ef9c22edbc','VhFfwsAnxr9OBfRvGWKsyr7H','0819c9ff210c24f9efcb16fc')
AND sc.is_active = 1
) AS tblA
JOIN
(SELECT count(target_id) AS numTwitterClicks
FROM stats_social_clicks AS sc
WHERE sc.social_network = 'twitter'
AND sc.campaign_id IN ('639ba3c9d86726f2ef5a6ca3','2bce996549ed7acb','f91491361140ccd81a7ab8bb','3d4d9a45bba4b8ef9c22edbc','VhFfwsAnxr9OBfRvGWKsyr7H','0819c9ff210c24f9efcb16fc')
AND sc.is_active = 1
) AS tblB
) as tbl3
WHERE campaignID IN ('639ba3c9d86726f2ef5a6ca3','2bce996549ed7acb','f91491361140ccd81a7ab8bb','3d4d9a45bba4b8ef9c22edbc','VhFfwsAnxr9OBfRvGWKsyr7H','0819c9ff210c24f9efcb16fc')

Related

Declare variables MySQL

I am trying to declare variables and run the query like this:
$sql = "SELECT #dateconsult := (YEARWEEK('2018-10-01',3)),
#countunits := ( SELECT COUNT(s.id_production)
FROM sw_sowing
WHERE status != 0
AND YEARWEEK(date,3) <= #dateconsult
GROUP BY id_production_unit_detail
),
#quadrants := ( SELECT DISTINCT value
FROM cf_config
WHERE parameter = 'PLANTHEALTH'
);
SELECT FORMAT(((count_quadrant * 100)/(total_units * Cuadrantes)),3) AS incidence
FROM (
SELECT #countunits AS total_units, #quadrants AS Cuadrantes,
FROM ph_planthealth
INNER JOIN ph_planthealth_detail ON ph_planthealth_detail.id_p = ph_planthealth.id
WHERE YEARWEEK(ph_planthealth.date,3) = #dateconsult
AND ph_planthealth.status = 200
AND ph_planthealth.id_tenant = 1
AND ph_planthealth_detail.id_plague != 0
GROUP BY ph_planthealth_detail.id_plague
) AS s
ORDER BY incidence DESC; ";
$plague = $this->db->fetchAll($sql, Phalcon\Db::FETCH_ASSOC, $options) ";
the problem is that it shows the result of the first SELECT which are the variables that I declared and not the one of the second SELECT that is the main query.
It's the first time I declare variables and I do not know if I'm doing it right.
I appreciate your comments and help regarding this topic.
You don't need to do the variable assignments in a separate SELECT. You can do them by joining with the main query.
SELECT FORMAT(((count_quadrant * 100)/(total_units * Cuadrantes)),3) AS incidence
FROM (
SELECT #countunits AS total_units, #quadrants AS Cuadrantes,
FROM ph_planthealth
INNER JOIN ph_planthealth_detail ON ph_planthealth_detail.id_p = ph_planthealth.id
WHERE YEARWEEK(ph_planthealth.date,3) = #dateconsult
AND ph_planthealth.status = 200
AND ph_planthealth.id_tenant = 1
AND ph_planthealth_detail.id_plague != 0
GROUP BY ph_planthealth_detail.id_plague
) AS s
CROSS JOIN (
SELECT #dateconsult := (YEARWEEK('2018-10-01',3)),
#countunits := ( SELECT COUNT(s.id_production)
FROM sw_sowing
WHERE status != 0
AND YEARWEEK(date,3) <= #dateconsult
GROUP BY id_production_unit_detail
),
#quadrants := ( SELECT DISTINCT value
FROM cf_config
WHERE parameter = 'PLANTHEALTH'
)
) AS vars
ORDER BY incidence DESC

Yii2 join a subquery

I'm building a booking site, where properties (ex: hotel) have rooms and you can book them.
I've made a raw SQL query which filters the available rooms in a specified date range, but I don't know how to implement it in a YII AR way: using with active record find() as a relation
Do you guys have any suggestion or opinion about this?
SELECT
property.id,
property_lang.name,
max_people.total
FROM property
JOIN property_lang ON (property.id = property_lang.property_id AND property_lang.lang_id = 'hu')
JOIN (
SELECT
property_id AS id,
sum(max_people) AS total
FROM room
WHERE room.id NOT IN (
SELECT room_id
FROM booking
JOIN booking_status ON (booking.last_status_id = booking_status.id)
JOIN booking_room ON (booking.id = booking_room.id)
JOIN property ON booking.property_id = property.id
WHERE (booking_status.status > -1 OR booking_status.status IS NULL)
AND booking.check_in < '2017-10-18'
AND booking.check_out > '2017-10-14'
)
GROUP BY property_id
) max_people
ON max_people.id = property_id
ORDER BY property.id
The simplest solution is use the createCommand with params:
\Yii::$app->db->createCommand("SELECT
property.id,
property_lang.name,
max_people.total
FROM property
JOIN property_lang ON (property.id = property_lang.property_id AND property_lang.lang_id = 'hu')
JOIN (
SELECT
property_id AS id,
sum(max_people) AS total
FROM room
WHERE room.id NOT IN (
SELECT room_id
FROM booking
JOIN booking_status ON (booking.last_status_id = booking_status.id)
JOIN booking_room ON (booking.id = booking_room.id)
JOIN property ON booking.property_id = property.id
WHERE (booking_status.status > -1 OR booking_status.status IS NULL)
AND booking.check_in < ':startdate'
AND booking.check_out > ':finishdate'
)
GROUP BY property_id
) max_people
ON max_people.id = property_id
ORDER BY property.id")
->bindValues([':startdate' => $startDate, ':finishdate' => $startDate])
->execute();
Other way is to split query for subqueries and try to use AR. It will be something like that:
$subSubQuery=Booking::find()
->select(['room_id'])
->join('booking_status', 'booking.last_status_id = booking_status.id')
->join('booking_room', 'booking.id = booking_status.id')
->join('property', 'booking.property_id= booking_propery.id')
->andWhere(['or',
['>','booking_status.status',-1],
[ 'booking_status.status'=>null],
])
->andWhere(['<','booking.check_in',$startDate])
->andWhere(['>','booking.checkout',$finishDate])
->groupBy('property_id');
$subQuery = Room::find()->select(['property_id as id','sum(max_people) as total'])->andFilterWhere(['not in', 'answers_metering.id', $subSubQuery]);
$query = Property::find()->select(['property.id','property_lang.name','max_people.total'])
->join($subQuery. ' as max_people', 'max_people.id = property.id')
->join('property_lang', 'property.id = property_lang.property_id AND property_lang.lang_id = \'hu\'')
->orderBy(['property.id' => SORT_ASC])
->all();

MySQL - SELECT WHERE condition based on value of another SELECT

Hello I have two MySQL Querys where I am trying to use count and results from first select in condition for the second select.
Here is my code:
$sql = "SELECT m.name, m.id
FROM members m
WHERE m.online_status = 1 {$dep} ORDER BY m.name ASC";
$sql_second = "SELECT time_management.clientid, clients.client,
SUM( CASE WHEN MONTH(`date`) = 1 AND taskid <> 1 AND YEAR(date)='$year' THEN TIME_TO_SEC( `time` ) AND user = (result from previouse slect) ELSE 0 END) AS (user_1)
FROM time_management
LEFT JOIN clients ON time_management.clientid = clients.id
WHERE {$dep_where} = {$department_var}
GROUP BY clientid";
So first select is selecting all users which are unknown value. Name and ID
In the second query what I need is to Select for example:
let's say the first query returns
id:1 name: Jon
id:2 name: Mike
id:3 name: Dave
Total results: 3
so in this case in the second query the following line have to be repeaded 3 times for each user:
SUM( CASE WHEN MONTH(`date`) = 1 AND taskid <> 1 AND YEAR(date)='$year' THEN TIME_TO_SEC( `time` ) AND user = (result from previouse slect) ELSE 0 END) AS (user_1)
where user will be = to 1,2,3 for each line and (user_1) willbe (user_2), (user_3)
Is there a way this operation to be realized directly inside MySQL ? if now how it should be solved ?

MySQL - Group by for UNION query

I've been trying to find a solution to my problem for a couple of hours now and can't come up with the right query. I have two tables, stocktake_scans and stocktake_items. I need to select data from both tables and group them together. The query that I have at the moment is this:
SELECT
a.department_description, a.sub_department_description, a.total_cost, a.total_retail, SUM(a.qty) AS qty, a.total_vat, a.vat_rate
FROM (
SELECT (CASE WHEN TRIM(IFNULL(sp.department_description, '')) = '' THEN 'N/A' ELSE sp.department_description END) AS department_description,
(CASE WHEN TRIM(IFNULL(sp.sub_department_description, '')) = '' THEN 'N/A' ELSE sp.sub_department_description END) AS sub_department_description,
SUM(sp.unit_cost_price * ss.quantity) AS total_cost,
SUM(sp.unit_retail_price * ss.quantity) AS total_retail,
sum(ss.quantity) AS qty,
(SUM(sp.unit_cost_price*ss.quantity)) * (sv.vat_rate/100) AS total_vat,
sv.vat_rate as vat_rate
FROM
stocktake_scans ss
INNER JOIN stocktake_products sp ON ss.stocktake_product_id = sp.stocktake_product_id
LEFT JOIN stocktake_vat_codes sv ON sv.vat_code = sp.vat_code AND sv.stocktake_id = '5778'
WHERE ss.stocktake_id = '5778'
GROUP BY sp.department_description, sp.sub_department_description
UNION ALL
SELECT (CASE WHEN TRIM(IFNULL(si.department_description, '')) = '' THEN 'N/A' ELSE si.department_description END) AS department_description,
'N/A' as sub_department_description,
SUM(si.unit_cost_price * si.quantity) AS total_cost,
SUM(si.unit_retail_price * si.quantity) AS total_retail,
sum(si.quantity) AS qty,
SUM(si.unit_cost_price * quantity)*(sv.vat_rate/100) AS total_vat,
sv.vat_rate as vat_rate
FROM stocktake_items si
LEFT JOIN stocktake_vat_codes sv ON sv.vat_code = si.vat_code AND sv.stocktake_id = '5778'
WHERE si.stocktake_id = '5778' GROUP BY si.department_description ) a
GROUP
BY a.department_description, a.sub_department_description
This doesn't fully do the job. I get all the data from stocktake_scans, followed by data from stocktake_items.
I get the below as the first result
And then at the end of the excel file I also get this
What is the right way of doing this, so that both Alcohol figures are displayed in one place?
Add ORDER BY a.department_description, a.sub_department_description before the last GROUP BY

Need to show SQL partial empty results

I need to show empty rows for BRANDS too. I mean, there is a third brand not shown in this query, look:
SELECT
da_brands.name AS brand_name,
COUNT(DISTINCT da_deals.id) AS total_deals,
0 AS total_downloaded_coupons,
0 AS total_validated_coupons,
COUNT(da_logs.id) AS total_likes
FROM
da_brands,
da_deals
LEFT JOIN da_logs
ON da_logs.fk_deal_id = da_deals.id
AND da_logs.fk_deal_id = da_deals.id
AND da_logs.type = 'deal_like'
WHERE da_brands.fk_club_id = 6
AND da_deals.fk_brand_id = da_brands.id
AND da_brands.date <= NOW()
GROUP BY da_brands.name
ORDER BY da_brands.name ASC
RESULTS:
brand_name total_deals total_downloaded_coupons total_validated_coupons total_likes
Marca2 2 0 0 1
Marca1 9 0 0 4
This conditional is showing only brands within deals but i want all brands...:
AND da_deals.fk_brand_id = da_brands.id
Any idea what statement should i use?
Thank you so much.!!!
This following line in the WHERE predicate is the problem...
AND da_deals.fk_brand_id = da_brands.id
You need to LEFT JOIN to da_deals, the same way you did to da_logs, and move that line above into the ON statement for the join.
See below...
SELECT
da_brands.name AS brand_name,
COUNT(DISTINCT da_deals.id) AS total_deals,
0 AS total_downloaded_coupons,
0 AS total_validated_coupons,
COUNT(da_logs.id) AS total_likes
FROM da_brands
LEFT JOIN da_deals
ON da_brands.id = da_deals.fk_brand_id
LEFT JOIN da_logs
ON da_logs.fk_deal_id = da_deals.id
AND da_logs.fk_deal_id = da_deals.id
AND da_logs.type = 'deal_like'
WHERE da_brands.fk_club_id = 6
AND da_brands.date <= NOW()
GROUP BY da_brands.name
ORDER BY da_brands.name ASC

Categories