MySQL: join to SELECT statement issue - mysql

I've created the following stored procedure:
CREATE PROCEDURE `sp_DBR_Subbie_Cert_Input`(inPlot_ID varchar(25), inSubbie varchar(25), inCertDate date, inCertDetails varchar(50), inCertGross float ) BEGIN
SELECT inPlot_ID as 'Plot[Unit]', inSubbie as 'Subcontractor[inSub_ID]', inCertDate as 'Date[inC_Date]', inCertDetails as 'Details[inC_Det]', inCertGross as 'Gross[inC_Gross]', a.tblCert_Number as 'Prev. Cert#', a.tblCert_Gross as 'Prev Gross[inC_Prev]'
FROM hilmark.tblcertificates_j a
JOIN
(SELECT max(tblcertificates_j.tblCert_ID) as MaxCertID,
tblcertificates_j.tblCert_XID456 as MaxSubbie, tblcertificates_j.tblCert_XIDJob as MaxPlot
FROM hilmark.tblcertificates_j
GROUP BY tblcertificates_j.tblCert_XIDJob) x
WHERE x.MaxCertID=a.tblCert_ID AND x.MaxPlot=inPlot_ID AND x.MaxSubbie=inSubbie;
END $$
What I am trying to achieve is to allow a user to enter a new invoice for a supplier for a site. The query retrieves the last invoice for that supplier and that site. This works great except when this is the first invoice for that supplier on that site - nothing is returned. What I really need is a left outer join but in my code if I substitute the join with a left join I get a syntax error.
Where am I going wrong here?

I declared a variable called Max_CerT_ID and set it's value to the Cert_ID from the table or to zero if it's a completely new supplier. I then use this variable in case statements.
DROP PROCEDURE IF EXISTS sp_DBR_Subbie_Cert_Input
$$
CREATE PROCEDURE `sp_DBR_Subbie_Cert_Input`(inPlot_ID varchar(25), inSubbie varchar(25), inCertDate date, inCertDetails varchar(50), inCertGross float )
BEGIN
declare Max_Cert_Id int(11);
set Max_Cert_Id=0;
select max(y.tblCert_ID) into Max_Cert_ID from
hilmark.tblcertificates_j y
where y.tblCert_XIDJob=inPlot_ID and y.tblCert_XID456=inSubbie
group by y.tblCert_XIDJob, y.tblCert_XID456 ;
select 'dbr.colstyle',6,'%0.0F';
select 'dbr.colstyle',7,'%0.0F';
select 'dbr.colstyle',8,'%0.0F';
select inPlot_ID as 'Plot[Unit]',
inSubbie as 'Subcontractor[inSub_ID]',
inCertDate as 'Date[inC_Date]',
case
when Max_Cert_Id=0 then 1
else (select a.tblCert_Number from hilmark.tblcertificates_j a where a.tblCert_ID=Max_Cert_ID)+1
end as 'Cert#',
upper(inCertDetails) as 'Details[inC_Det]',
inCertGross as 'Gross[inC_Gross]',
case
when Max_Cert_Id=0 then 0
else (select a.tblCert_Gross from hilmark.tblcertificates_j a where a.tblCert_ID=Max_Cert_ID)
end as 'Prev. Gross',
case
when Max_Cert_Id=0 then inCertGross
else inCertGross-(select a.tblCert_Gross from hilmark.tblcertificates_j a where a.tblCert_ID=Max_Cert_ID)
end as 'Change in WIP';
END
$$

Try writing the query as:
SELECT inPlot_ID as `Plot[Unit]`, inSubbie as `Subcontractor[inSub_ID]`,
inCertDate as `Date[inC_Date]`, inCertDetails as `Details[inC_Det]`,
inCertGross as `Gross[inC_Gross]`, c.tblCert_Number as `Prev. Cert#`,
c.tblCert_Gross as `Prev Gross[inC_Prev]`
FROM hilmark.tblcertificates_j c LEFT JOIN
(SELECT max(c.tblCert_ID) as MaxCertID, c.tblCert_XID456 as MaxSubbie,
c.tblCert_XIDJob as MaxPlot
FROM hilmark.tblcertificates_j c
GROUP BY c.tblCert_XIDJob
) cmax
WHERE cmax.MaxCertID = c.tblCert_ID AND cmax.MaxPlot = c.inPlot_ID AND cmax.MaxSubbie = c.inSubbie;
Some notes:
I doubt this really does what you want, because MaxSubbie has an indeterminate value. But you save the query works. Why do you need both comparisons?
When using table aliases, make them abbreviations for the table so the query is easier to read.
Only use single quotes for string and date constants.

Related

Error Code 1241 - Operand should contain 1 column(s)

I was creating a procedure and I came across this.
Does anyone know how to solve this?
delimiter $$
create procedure sp_cadastraAluno(
in nome varchar(150),
in chamada varchar(3),
in data date,
in ra varchar(12),
in turma varchar(50),
in cpf varchar(14))
begin
declare x int;
set x = (select * from tb_coordenador inner join tb_professor
on tb_coordenador.cd_coord = tb_professor.cd_coord
inner join prof_turma on
tb_professor.cd_prof = prof_turma.cd_prof
inner join tb_turma on
prof_turma.cd_turma = tb_turma.cd_turma
inner join tb_aluno on
tb_turma.cd_turma = tb_aluno.cd_turma where nm_turma = turma and tb_professor.cd_cpf = cpf);
insert into tb_aluno(nm_aluno, cd_chamada, dt_nascimento, cd_ra, cd_turma) values
(nome, chamada, data, ra, x);
end $$
I need to insert in tb_aluno and for this, I need to pull the code already inserted in tb_turma, but this error appears.
You can't set variable 'x' with multiple columns. try removing select * and replace with the column which you need.

How to pass value for wherein in procedure of mysql

DELIMITER //
DROP PROCEDURE IF EXISTS salary_ref//# MySQL returned an empty result set (i.e. zero rows).
# MySQL returned an empty result set (i.e. zero rows).
CREATE PROCEDURE salary_ref(con int(11),IN id varchar(120),maxval int(11),minval int(11) , taxo int(11))
BEGIN
DECLARE s VARCHAR(50);
IF con = 1 THEN
SELECT `i` . * , `taxo`.`id` , `t`.`item_id` AS id, `u`.`name` AS user_name, `t`.`value` AS val
FROM (
`taxonomy` AS taxo
)
JOIN `item_taxo` AS t ON `t`.`taxo_id` = `taxo`.`id`
INNER JOIN `items` AS i ON `i`.`id` = `t`.`item_id`
INNER JOIN `users` AS u ON `u`.`id` = `i`.`created_by`
WHERE `t`.`value`
BETWEEN minval
AND maxval
AND `t`.`taxo_id` = taxo
AND `i`.`parent_tag_id` in (id);
ELSE
SELECT `i` . * , `taxo`.`id` , `t`.`item_id` AS id, `u`.`name` AS user_name, `t`.`value` AS val
FROM (
`taxonomy` AS taxo
)
JOIN `item_taxo` AS t ON `t`.`taxo_id` = `taxo`.`id`
INNER JOIN `items` AS i ON `i`.`id` = `t`.`item_id`
INNER JOIN `users` AS u ON `u`.`id` = `i`.`created_by`
WHERE `t`.`value`
BETWEEN minval
AND maxval
AND `t`.`taxo_id` = taxo
AND `i`.`parent_tag_id` in (id);
END IF;
END;
//# MySQL returned an empty result set (i.e. zero rows).
DELIMITER ;
//calling of that
call salary_ref(2,"\'36\',\'50\',\'57\'",17000000,0,7)
this is not work for me.
Following changes would solve the issues.
Change 1:
I suggest to not use same parameter names for stored procedure to represent column names of tables.
Unless you handle them properly there would arise an identifier conflict but does not seem to be there.
Change procedure signature as follows:
CREATE PROCEDURE salary_ref(
_con int(11), IN csv_id_values varchar(120),
_maxval int(11), _minval int(11), _taxo int(11)
)
Change 2:
You are trying to pass comma separated values for id field to use in where clause.
But using escape character won't solve your problem and that is not correct way of using input values.
call salary_ref( 2, '36,50,57', 17000000, 0, 7 )
The CSV value '36,50,57' can be used as is for where clause.
See the suggested Change below.
Change 3:
You can use FIND_IN_SET on CSV values instead of IN in the WHERE clause.
WHERE `t`.`value` BETWEEN _minval AND _maxval
AND `t`.`taxo_id` = _taxo
AND FIND_iN_SET( `i`.`parent_tag_id`, csv_id_values );
And, I think your procedure body is incomplete. Your IF con and ELSE are using the same SELECT statement. It is redundant, unless you change it.

Stored Procedure Can't drop temp table it don't exist

SQL Server 2008
This is a continuation of my last question. Now I'm trying to create a stored procedure, however I can't execute it. When I execute it, an error message displays
"Cannot drop the table #MyReport", because it does not exist or you do not have permissions.
Please guide me in the right direction.
Below is my stored Procedure
Create PROCEDURE [dbo].[SEL_MyReport]
(
#employeeid int,
#date1 datetime,
#date2 datetime
)
AS
BEGIN
drop table #MyReport
Create Table #MyReport
(
employeeid int,
name varchar(30),
department varchar(30),
checkTime datetime
)
if (#employeeid > 0)
Begin
INSERT INTO #MyReport (employeeid,name, department, checkTime)
select emp.EmpolyeeID, emp.Name,dep.DeptName,tm.checkTime
from TimeInOut tm
left join Employee emp on emp.EmpolyeeId = tm.EmployeeId
left join Department dep on dep.DeptID = emp.defaultDeptID
where (DATEDIFF(s,#date1,tm.checktime) >=0
and DATEDIFF(s,#date2,tm.checktime)<=0) and emp.employeeID = #employeeid
SELECT
employeeid
,name
,department
,[Time In] = MIN(checkTime)
,[Time Out] = MAX(checkTime)
FROM #MyReport
GROUP BY employeeid,name, department, CAST(checktime AS DATE)
End
Else
Begin
INSERT INTO #MyReport (employeeid,name, department, checkTime)
select emp.EmpolyeeID, emp.Name,dep.DeptName,tm.checkTime
from TimeInOut tm
left join Employee emp on emp.EmpolyeeId = tm.EmployeeId
left join Department dep on dep.DeptID = emp.defaultDeptID
where (DATEDIFF(s,#date1,tm.checktime) >=0
and DATEDIFF(s,#date2,tm.checktime)<=0)
SELECT
employeeid
,name
,department
,[Time In] = MIN(checkTime)
,[Time Out] = MAX(checkTime)
FROM #MyReport
GROUP BY employeeid,name, department, CAST(checktime AS DATE)
End
END
Go
exec SEL_MyReport('639','05/01/2014','05/08/2014')
There is quite a bit I would change - here is the code.
You will notice
branching logic (if #employeeid > 0) has been replaced by a slightly more verbose WHERE clause
no need for #tables as far as I can tell, the SELECT should suffice
Unfortunately, I do not have anything to test against, but you should understand the general impression of it.
Further, your date filtering seemed quite strange, so I assumed you may have meant something else - I could be mistaken. Either way, the way the date filtering is now done is SARGable
CREATE PROCEDURE [dbo].[SEL_MyReport]
(
#employeeid INT,
#date1 DATETIME,
#date2 DATETIME
)
AS
BEGIN
SET NOCOUNT ON;
SELECT emp.EmpolyeeID
,emp.Name
,dep.DeptName
,[Time In] = MIN(tm.checkTime)
,[Time Out] = MAX(tm.checkTime)
FROM TimeInOut tm
LEFT
JOIN Employee emp on emp.EmpolyeeId = tm.EmployeeId
LEFT
JOIN Department dep on dep.DeptID = emp.defaultDeptID
WHERE tm.checktime >= #date1
AND tm.checktime <= #date2
/***********************************************************************************************************
* I've assumed what you may be trying to express, above
* You might also want to look at the BETWEEN() operator, remembering that it is inclusive in its behaviour
* (DATEDIFF(s,#date1,tm.checktime) >=0
* AND DATEDIFF(s,#date2,tm.checktime)<=0)
***********************************************************************************************************/
AND (emp.employeeID = #employeeid OR #employeeid <= 0)
GROUP BY emp.EmpolyeeID, emp.name, dep.department, CAST(tm.checktime AS DATE)
END
GO
Well, since the very first step of your Stored Procedure attempts to drop a table, this will obviously result in an error if that table does not exist.
To work around this, make sure you check whether the table exists, before you drop it:
IF OBJECT_ID('tempdb..#MyReport') IS NOT NULL DROP
TABLE #MyReport

Eliminating Duplicate Rows after Modifying Stored Procedure

Our Purchasing Department wants me to modify our application so that Requisition Requests can be searched using Part Numbers.
Each Requisition Request will contain at least one part, but could contain several parts.
The Stored Procedure is set up so that fields may be populated or they may not be, so it pulls data based on what is passed in.
Here is how the Stored Procedure works before my modifications:
ALTER PROCEDURE [dbo].[GetRequisitions](#status_id int, #startdate varchar(50), #enddate varchar(50),
#Vendor_Name varchar(200), #PO_Number varchar(50), #Req_ID int, #datesearch bit, #Part_ID varchar(50)) AS
BEGIN
SET NOCOUNT ON;
select
a.Req_ID, a.Vendor_ID, a.Vendor_Name, a.Req_Date, a.PO_Number, a.Requested_Buy, a.approved,
b.status,
c.supervisor_login,
case when d.req_id is not null then 1 else 0 end as HasDocs
from Req as a
join Status as b on (a.Status_ID=b.Status_ID)
left outer join Supervisor as c on (a.Requested_Login=c.Emp_Login)
left outer join req_doc as d on (a.Req_ID=d.req_id)
where
((#datesearch is null or #datesearch=0) or (a.Req_Date between #startdate and #enddate))
and ((#status_id is null or #status_id=0) or (a.Status_ID=#status_id))
and ((#Vendor_Name is null or LEN(RTrim(#Vendor_Name))=0) or (a.Vendor_Name like '%'+#Vendor_Name+'%'))
and ((#PO_Number is null or LEN(RTrim(#PO_Number))=0) or (a.PO_Number like #PO_Number+'%'))
and ((#Req_ID is null or #Req_ID=0) or (a.Req_ID=#Req_ID))
END
To query this same DataSet using an optional Part Number Part_ID field, I added the following code that joins with the Req_Part DataTable:
ALTER PROCEDURE [dbo].[GetRequisitions](#status_id int, #startdate varchar(50), #enddate varchar(50),
#Vendor_Name varchar(200), #PO_Number varchar(50), #Req_ID int, #datesearch bit, #Part_ID varchar(50)) AS
BEGIN
SET NOCOUNT ON;
select
a.Req_ID, a.Vendor_ID, a.Vendor_Name, a.Req_Date, a.PO_Number, a.Requested_Buy, a.approved,
b.status,
c.supervisor_login,
case when d.req_id is not null then 1 else 0 end as HasDocs
from Req as a
join Status as b on (a.Status_ID=b.Status_ID)
left outer join Supervisor as c on (a.Requested_Login=c.Emp_Login)
left outer join req_doc as d on (a.Req_ID=d.req_id)
join Req_Part e on (a.Req_ID=e.Req_ID)
where
((#datesearch is null or #datesearch=0) or (a.Req_Date between #startdate and #enddate))
and ((#status_id is null or #status_id=0) or (a.Status_ID=#status_id))
and ((#Vendor_Name is null or LEN(RTrim(#Vendor_Name))=0) or (a.Vendor_Name like '%'+#Vendor_Name+'%'))
and ((#PO_Number is null or LEN(RTrim(#PO_Number))=0) or (a.PO_Number like #PO_Number+'%'))
and ((#Req_ID is null or #Req_ID=0) or (a.Req_ID=#Req_ID))
and ((#Part_ID is null or LEN(RTrim(#Part_ID))=0) or (e.Part_ID like '%'+#Part_ID+'%'))
END
What is the best way to get this to stop returning the duplicate rows?
And, as a FYI: I did not design this database! I am aware of the fact that the column name Requested_Buy would be correctly spelled as Requested_By, but the database is already in production. Misspelled words really irritate me!
If I understood correctly, you may update query like this.
select
a.Req_ID, a.Vendor_ID, a.Vendor_Name, a.Req_Date, a.PO_Number, a.Requested_Buy, a.approved,
b.status,
c.supervisor_login,
case when d.req_id is not null then 1 else 0 end as HasDocs
from Req as a
join Status as b on (a.Status_ID=b.Status_ID)
left outer join Supervisor as c on (a.Requested_Login=c.Emp_Login)
left outer join req_doc as d on (a.Req_ID=d.req_id)
where
((#datesearch is null or #datesearch=0) or (a.Req_Date between #startdate and #enddate))
and ((#status_id is null or #status_id=0) or (a.Status_ID=#status_id))
and ((#Vendor_Name is null or LEN(RTrim(#Vendor_Name))=0) or (a.Vendor_Name like '%'+#Vendor_Name+'%'))
and ((#PO_Number is null or LEN(RTrim(#PO_Number))=0) or (a.PO_Number like #PO_Number+'%'))
and ((#Req_ID is null or #Req_ID=0) or (a.Req_ID=#Req_ID))
and ( ISNULL(#Part_ID,0) = 0
OR
EXISTS(SELECT NULL FROM Req_Part e WHERE a.Req_ID=e.Req_ID AND e.Part_ID like '%'+#Part_ID+'%')
)

mysql stored procedure column error

I receive the following error. But I havent typed count in my stored procedure so why is it giving this error?
CALL updateproposalStatus(1,5) Error Code: 1136. Column count doesn't match value count at row 1
STORED PROCEDURE:
CREATE DEFINER=`root`#`localhost` PROCEDURE `updateProposalStatus`(IN decision INT, IN x INT)
BEGIN
DECLARE adv_id varchar(30);
DECLARE std_id varchar(30);
DECLARE topic varchar(255);
select
a.id INTO adv_id
from
rp_proposal p
inner join rp_adviser a on p.rp_adviser_id = a.id
where p.proposal_id=x;
select
s.id INTO std_id
from
rp_proposal p
inner join rp_student s on p.rp_student_id = s.id
where p.proposal_id=x;
select
p.title INTO topic
from
rp_proposal p
where p.proposal_id=x;
UPDATE rp_proposal_status
SET state_rp_controller =decision
WHERE rp_proposal_id = x;
IF decision = 1 THEN
INSERT INTO rp_indpstudy VALUES (topic,adv_id,std_id);
END IF;
END
It's the column-count (number of columns) that it is complaining about, not about a column named count.
Most likely culprit is the insert statement at the end - make sure that it is consistent with rp_indpstudy's schema.