i have the following stored procedure that returns the sent emails of the latest or last inserted campaigns
"Now my aim to only show the campaigns which have "sent: count greater than "0" how could i make changes to the following sp to do it, because now it is returning all the campaigns including "0" and greater than "0" "..
Code is...
DELIMITER $$
DROP PROCEDURE IF EXISTS `couponcrusaderdev`.`sp_tblemailcampaignLoadTop4`$$
CREATE DEFINER=`anyone`#`000.000.00.00` PROCEDURE `sp_tblemailcampaignLoadTop4`(p_UserID Int(11))
SQL SECURITY INVOKER
BEGIN
SELECT EC.*,(Select MailChimpCampaignID from tblcampaignschedule where EC.CampaignID=tblcampaignschedule.CampaignID ) as MailChimpCampaignID,(Select count(MailChimpCampaignID) from tblcampaignschedule) as msent,CT.CampaignType, (Select tblcampaignschedule.ScheduleDateTime from tblcampaignschedule
where EC.CampaignID=tblcampaignschedule.CampaignID order By ScheduleDateTime desc limit 1) as CampaignDateTime,
(Select Count(*) from tblemailsent ES
inner join tblcampaignschedule CS on CS.CampaignSceduleID= ES.CampaignSceduleID
where ES.Status= 'ProcessedMessage' and CS.CampaignID = EC.CampaignID)as Sent
FROM tblemailcampaign EC
inner join tblcampalgntype CT on CT.CampaignTypeID= EC.CampaignTypeID
inner join tblcompanies C On EC.CompanyID = C.CompanyID
WHERE (p_UserID = 0 OR C.AddUserID = p_UserID)
order by CampaignDateTime desc limit 4
;
END$$
DELIMI
You should use HAVING
HAVING COUNT(sent) >= 0;
Manual:
http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html
Related
I am working on converting a T-SQL stored procedure into MySQL. I am not familiar with T-SQL and am working on becoming more familiar with temp tables and stored procedures. Thanks for your help in advance.
The T-SQL original looks like this (EDIT: note this is only a portion of the original procedure used to produce a report):
DROP TABLE IF EXISTS #accounts;
SELECT d.data_id
,p.pp_name AS name
,CONVERT(tinyint,1) AS flag
,d.pd_date
,CONVERT(char(6),pd_date,112) AS date_period
,CONVERT(varchar(3),0) AS n_phones
INTO #accounts
from table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND DATEDIFF(MONTH,pd_date,GETDATE()) < 3
UPDATE a
SET a.flag = 0
FROM #accounts a
JOIN table_detail d ON a.data_id = d.data_id
JOIN table_pool p ON d.pp_id = p.pp_id
WHERE d.pd_date < a.pd_date
AND pp_name != 'error';
My current update is below. Do I need to wrap this in a CREATE TEMPORARY TABLE IF NOT EXISTS accounts AS (<insert query here>) instead of the INTO #accounts?
SELECT d.data_id
,p.pp_name AS name
,CONVERT(tinyint,1) AS flag
,d.pd_date
,DATE_FORMAT(pd_date,'%Y%m%d') AS date_period
,CONVERT(varchar(3),0) AS n_phones
FROM table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND TIMESTAMPDIFF(MONTH,pd_date,NOW()) < 3
Then do something like this assuming the syntax is right:
UPDATE accounts a -- Is this the correct way to add an alias and update the temp table?
JOIN table_detail d ON a.data_id = d.data_id
JOIN table_pool p ON d.pp_id = p.pp_id
SET a.flag = 0
WHERE d.pd_date < a.pd_date
AND pp_name != 'error';
Finally, I assume I could follow this post to wrap the final query into a stored procedure, correct? To summarize the code in the post:
drop procedure if exists procedure_name;
DELIMITER $$
create procedure procedure_name ()
BEGIN
DROP TEMPORARY TABLE IF EXISTS accounts;
CREATE TEMPORARY TABLE accounts AS (
SELECT...
FROM...
WHERE...
;
)
UPDATE accounts
JOIN ...
JOIN ...
SET...
WHERE...;
DROP TEMPORARY TABLE accounts; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
I wanted to post the solution that finally worked for me for others that might be having the same issue. The code below resolves this.
DROP PROCEDURE IF EXISTS procedure_name;
DELIMITER $$
CREATE PROCEDURE procedure_name ()
BEGIN
DROP TEMPORARY TABLE IF EXISTS accounts;
CREATE TEMPORARY TABLE accounts AS (
SELECT d.data_id
,p.pp_name AS name
,1 AS flag
,d.pd_date
,DATE_FORMAT(pd_date,'%Y%m%d') AS date_period
,CONVERT(varchar(3),0) AS n_phones
FROM table_detail d
JOIN table_pool p ON d.pp_id = p.pp_id
JOIN table_type t ON p.pp_type_id = t.pp_type_id
JOIN Inventory i ON d.data_id = i.data_id
JOIN Product pr ON i.product_id = pr.product_id
WHERE pp_name IN (SELECT name FROM Sandbox..desired_sandbox)
AND TIMESTAMPDIFF(MONTH,pd_date,NOW()) < 3
);
-- Update the temp table based on specified criteria
UPDATE accounts
JOIN ...
JOIN ...
SET...
WHERE...;
-- Create final Query for report
SELECT ...
FROM accounts
WHERE ...
GROUP BY ... -- whatever you need for final query
DROP TEMPORARY TABLE accounts; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
However, it is important to note the limits of MySQL temporary tables. Although I did not indicate it in my original post, later, I was attempting to join the temporary table onto itself. I needed to follow the suggestion outlined here. Essentially, if you need to refer to a temp table with itself you need to make a copy of the temp table: CREATE TEMPORARY TABLE accounts2 AS (SELECT * FROM accounts). Then you can join a temp table to itself.
While creating procedure following error occurs:
Error Code: 1221. Incorrect usage of UNION and INTO
My Procedure is:
SET sql_mode=ORACLE;
DELIMITER $$
CREATE PROCEDURE MARK_ATTENDANCE (IN EmployeeId INTEGER)
BEGIN
DECLARE EmpShift INTEGER(10);
DECLARE EmpMarkLoc INTEGER(10);
SET EmpShift = 0;
SET EmpMarkLoc = 0;
SELECT ed.default_shift, sl.location_id INTO EmpShift,EmpMarkLoc
FROM EMPLOYEE ed
LEFT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
UNION ALL
SELECT ed.default_shift, sl.location_id
FROM EMPLOYEE ed
RIGHT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
WHERE sl.sublocation_id IS NULL
AND emp_id = EmployeeId;
END ;
$$
DELIMITER ;
Actually I wanted a FULL OUTER JOIN and ended up on UNION ALL and tried to store output in some variables like EmpShift and EmpMarkLoc for further usage.
SELECT #EmpShift:=ed.default_shift, #EmpMarkLoc:=sl.location_id
used above in place of
SELECT ed.default_shift, sl.location_id INTO EmpShift,EmpMarkLoc
You can put the unioned queries in a derived table and select from there into the variables
SELECT u.default_shift,
u.location_id
INTO empshift,
empmarkloc
FROM (SELECT ed.default_shift,
sl.location_id
FROM employee ed
LEFT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
UNION ALL
SELECT ed.default_shift,
sl.location_id
FROM employee ed
RIGHT JOIN sublocation sl
ON sl.sublocation_id = ed.sub_location_id
WHERE sl.sublocation_id IS NULL
AND emp_id = employeeid) u;
But be aware, if the unioned querys can select more than one row an assignment to scalar variables is problematic.
The outer stored procedure gives me the product name and the raw material required for it and inner stored procedure gives me the quantity of stored procedure in my warehouse .(for eg: when I search for chocolate(i.e name_grey) in outer stored procedure I get columns with the raw material use to make chocolate(i.e )milk and sugar. Now I want to put milk and sugar as input of inner stored procedure. (where yarnstock1 is my inner stored procedure)
How do i do that?
I tried to call complete inner stored procedure in outer stored procedure. Here when i give input chocolate to outer stored procedure i get appropriate column details and i get detail of all raw material which i don't want.
---------------------------------whole stored procedure ---------------------
CREATE DEFINER=`root`#`localhost` PROCEDURE `finalgrey`(IN name_grey varchar(250))
BEGIN
SELECT
orderDate,
productname,
warpyarnid,
warpyarn ,
sum(warpneeded * meters_left) as warpneeded ,
weftyarnid,
weftyarn,
sum(weftneeded * meters_left) as weftneeded,
sum(order_quantity), sum(invoice_quantity), sum(meters_left)
FROM
(SELECT
s.orderDate,s.orderToDate,
s.orderid AS saudaid,
c.orderId AS challanid,
pm.productname,
qc.warpyarnid,
pwarp.productname AS warpyarn,
(warperwt / 100) AS warpneeded,
qc.weftyarnid,
pweft.productname AS weftyarn,
(weftwt / 100) AS weftneeded,
(sum(s.totalQuantity)/count(i.invoiceId)) AS order_quantity,
sum(i.totalQuantity) AS invoice_quantity,
IF(((sum(s.totalQuantity)/count(i.invoiceId)) - SUM(i.totalQuantity)) <0, "0", ((sum(s.totalQuantity)/count(i.invoiceId)) - SUM(i.totalQuantity)) ) as meters_left
FROM
sauda AS s
LEFT JOIN
challan c ON s.orderid = c.orderId
LEFT JOIN
invoice AS i ON c.challanid = i.challanid
LEFT JOIN
productmaster pm ON pm.productmasterid = s.itemId
LEFT JOIN
qualitymaster q ON q.productid = pm.productmasterid
LEFT JOIN
qualityconfig qc ON qc.qualityid = q.qualitymasterid and qc.active = 0
LEFT JOIN
productmaster pweft ON pweft.productmasterid = qc.weftyarnid
LEFT JOIN
productmaster pwarp ON pwarp.productmasterid = qc.warpyarnid
WHERE
s.active = 0 AND i.active = 0
AND c.active = 0
AND s.orderDate >= '2018-04-01' and s.orderType = 'Sales' and orderToDate >= CURDATE()
group by s.orderid ) xcx
where productname LIKE CONCAT('%', name_grey , '%')
group by productname;
call yarnstock1('');
END
---------------------------------inner stored procedure-----------------------
CREATE DEFINER=`root`#`localhost` PROCEDURE `yarnstock1`(in warp_yarn varchar(250))
BEGIN
select sum(itna_aayega) , itemId ,productmasterid,productname,sum(itna_bacha)
from
(select s.orderId,s.orderDate,s.orderToDate,s.itemId,py.purchaseyarnid, iys.inwardyarnstockid,
iys.purchaseorderid,(s.totalQuantity),sum(iys.totalkgs) as itna_aaya, pm.productmasterid,pm.productname,
CASE WHEN orderToDate<current_date() THEN "0"
WHEN orderToDate>current_date() AND s.totalQuantity < sum(iys.totalkgs) THEN "0"
ELSE s.totalQuantity - sum(iys.totalkgs) END AS itna_aayega,
if(orderToDate<current_date(),"0", (sum(iys.finalkgs) * 1)) as itna_bacha #group_concat(iys.totalkgs)
from sauda s
LEFT JOIN purchaseyarn py
ON s.orderId = py.purchaseorderid
LEFT JOIN inwardyarnstock iys
on py.purchaseyarnid = iys.purchaseyarnid
left join productmaster pm on s.itemId = pm.productmasterid
where iys.active =0 and s.active =0 and py.active = 0 and s.orderDate >= '2018-04-01' and s.type = 'yarn' and s.orderType = 'purchase'
group by s.orderId) xxx
where productname LIKE CONCAT( warp_yarn, '%')
group by itemId ;
END[]
If you want to pass / receive table structure to / from an another stored procedure, you can use a temporary table. A temporary table is visible throughout the connection and a temporary table created in a stored procedure is visible to other stored procedures within same connection.
delimiter $$
drop procedure if exists getEmptySeats $$
create procedure getEmptySeats(flight_number char(5),flight_date date)
begin
select seatingID as Seats, concat(Seats.rowNumber, Seats.seatNumber) as Seat
from Seating
where
aircraftID = aircraft_id and
seatID not in
( Select seatID from Seating
inner join Seats on Seating.seatID = Seats.seatID
inner join Booking on Seating.bookingNumber = Booking.bookingNumber
inner join Flights on Booking.flightCode = Flights.flightCode
inner join FlightSchedule on Flights.flightNumber = FlightSchedule.flightNumber
where flightNumber = flight_number and flightDate = flight_date)
order by seatingID;
end $$
ORDER BY RAND()
LIMIT 1
delimiter ;
The procedure is suppose to give a random seat in a specific airplane.
I have no idea what is wrong and I have searched the internet for so long and haven't found any thing that helped.
When I call the procedure it gives this:
Error Code: 1054. Unknown column 'Seats.rowNumber' in 'field list'
Here is the Seats table:
seatID INT(11)
rowNumber TINYINT(4)
seatNumber CHAR(1)
seatPlacement VARCHAR(15)
plainID CHAR(6)
You need to join it with Seats table. The one used as a subquery can not be accessed directly
As #Madhivanan mentioned, you need to join it with the Seats table.
There were also a few ambiguous columns which needed fixing (prefixing with the table name usually is the easiest answer unless you give the table an alias)
delimiter $$
drop procedure if exists getEmptySeats $$
create procedure getEmptySeats(flight_number char(5),flight_date date)
begin
select seatingID as Seats, concat(Seats.rowNumber, Seats.seatNumber) as Seat
from Seating
inner join Seats on Seating.seatID = Seats.seatID
where
aircraftID = aircraft_id and
seating.seatID not in
( Select seating.seatID from Seating
inner join Seats on Seating.seatID = Seats.seatID
inner join Booking on Seating.bookingNumber = Booking.bookingNumber
inner join Flights on Booking.flightCode = Flights.flightCode
inner join FlightSchedule on Flights.flightNumber = FlightSchedule.flightNumber
where Flights.flightNumber = flight_number and flightDate = flight_date)
order by seatingID;
end $$
ORDER BY RAND()
LIMIT 1
delimiter ;
I have written a procedure that shows me the image path from picture table and I want to calculate the no. of unread messages.Here is what i am doing
CREATE PROCEDURE datehate.dashboard_message(IN UserID INT)
BEGIN
SELECT picture.path_thumb,status
FROM picture,message,user_profile
WHERE (
(message.receiver_user_id=UserID)
AND
(user_profile.user_id=message.sender_user_id AND picture.picture_id=user_profile.picture_id)
);
END
And this the output i am getting
path_thumb status
E:\DateOrHateUser\DEMO_2_Stockhlom\images\Male\1#j... UNREAD
E:\DateOrHateUser\DEMO_2_Stockhlom\images\Male\3#j... READ
E:\DateOrHateUser\DEMO_2_Stockhlom\images\Male\5#j... UNREAD
use
SELECT count(*)
to get the number of records returned
and put
status="UNREAD"
in your WHERE condition
How about -
CREATE PROCEDURE datehate.dashboard_message(IN UserID INT)
BEGIN
SELECT p.path_thumb, SUM(IF(m.status = 'UNREAD', 1, 0)) AS unread_msgs
FROM message m
INNER JOIN user_profile up
ON m.sender_user_id = up.user_id
INNER JOIN picture p
ON up.picture_id = p.picture_id
WHERE m.receiver_user_id=UserID
GROUP BY m.sender_user_id, p.path_thumb;
END
EDIT I have modified the above query to give the count of unread messages without excluding senders for whom you have no unread messages. Sorry, I misunderstood your question.
or this which will give you the count of messages in each status -
CREATE PROCEDURE datehate.dashboard_message(IN UserID INT)
BEGIN
SELECT p.path_thumb, m.status, COUNT(*) AS msgs
FROM message m
INNER JOIN user_profile up
ON m.sender_user_id = up.user_id
INNER JOIN picture p
ON up.picture_id = p.picture_id
WHERE m.receiver_user_id=UserID
GROUP BY m.sender_user_id, p.path_thumb, m.status;
END