Managing database view to get proper result - mysql

I have view which gives reasonably correct answer:
DELIMITER $$
DROP VIEW IF EXISTS `test`.`new_temp`$$
CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost` SQL SECURITY DEFINER VIEW `new_temp` AS
SELECT `temp`.`pcount` AS `ind_type`,SUM(`temp`.`pcount`) AS `Index_val` FROM `temp` UNION ALL
SELECT `temp`.`ncount` AS `sum`,SUM(`temp`.`ncount`) AS `ncount` FROM `temp` $$
DELIMITER ;
Ouput:
ind_type Index_val
----------------------
2 23
2 34
I want it to give this kinda output:
New_temp
ind_type Index_val
-------------------------------
pcount 23
ncount 34
Problem is with code I have written. I tried in different way but i did not get it. any idea?

What you are trying to get is actual name of the column rather than it's value. In such case instead of saying
SELECT `temp`.`pcount` AS `ind_type`
Do it like
SELECT 'pcount' AS `ind_type`
EDIT:
Not sure what do you mean by giving same result. I tried the same and it worked fine; as below
create table temp (pcount int,ncount int);
insert into temp values(22,33);
insert into temp values(23,43);
create VIEW new_temp as
select 'pcount' AS 'ind_type',sum(pcount) as 'ind_val'
from temp
union
select 'ncount' AS 'ind_type',sum(ncount) as 'ind_val'
from temp;
Check this SQL fiddle http://sqlfiddle.com/#!2/bbcf6/1

Normally, you would have the values in a normalized dictionary table or similar. But since you don't provide any of that in your query, the below should give the desired result.
SELECT 'pcount' AS `ind_type`,SUM(`temp`.`pcount`) AS `Index_val` FROM `temp` UNION ALL
SELECT 'ncount' AS `ind_type`,SUM(`temp`.`ncount`) AS `ncount` FROM `temp` $$

Related

I keep getting zeros when I call a procedure that should be calling data I know exists

I'm trying to write a stored procedure in MySQL and then call it back, and I have to submit a screenshot of the procedure returning a correct response. The code for storing the procedure seems to work fine (no errors, at least), but when I run the CALL function it returns 0.00 no matter which number I put in for #column3. My instructor thinks the issue is stating the OUT as AmountDue before I define the variable at the very top, but I couldn't figure out another way to have an input for #column3 in the CALL function without the IN/OUT constraints. I'm very new at this, obviously, so forgive me if I'm missing something obvious...Anyone got any ideas?
Also, I don't need any help with building the database, adding tables, anything like that. The database exists and functions appropriately. Only need help on storing the procedure and calling it back. Thanks.
delimiter //
DROP PROCEDURE IF EXISTS GetAmountDue;
CREATE PROCEDURE GetAmountDue(IN order_num INT, OUT AmountDue DECIMAL(10,2))
BEGIN
DECLARE AmountDue DECIMAL(10,2) DEFAULT 0;
SELECT COST
INTO #AmountDue
FROM cake_shape
INNER JOIN ll_cakery.order
ON cake_shape.shape_id=order.shape_id
WHERE order_num=#order_num;
SELECT AmountDue;
END//
delimiter ;
CALL GetAmountDue('113',#AmountDue);
order_num is a column with individual 3-character integer data values
cost is a column with individual decimal(10,2) data values
cake_shape is a table
ll_cakery.order is a table (that doesn't work quite right because
mysql has a command ORDER so I have to give the schema name)
shape_id is a column, only used in the procedure for the join
in the CALL function, #order_num=113
You are passinf a string not an int
You don't compare column 3 with column1
Last you have to set the output variable with the data ou get from the select
Last never name variables like columns name, that brings only problems
CREATE tABLE table1 ( COST DECIMAL(19,2),column2 int, column3 int)
INSERT INTO table1 VALUES (10.2,1,1),(10.2,1,1)
CREATE TABLE table2 (column2 int)
INSERT INTO table2 VALUES (1)
CREATE PROCEDURE GetAmountDue(IN _column1 INT, OUT _AmountDue DECIMAL(10,2))
BEGIN
SELECT SUM(COST)
INTO #AmountDue
FROM table1
INNER JOIN table2
ON table1.column2=table2.column2
WHERE column3=_column1;
SET _AmountDue := #AmountDue;
END
CALL GetAmountDue(1,#AmountDue);
SELECT #AmountDue
| #AmountDue |
| ---------: |
| 20.40 |
db<>fiddle here

MySql procedure unable to filter query result properly for string input

I have following procured in my MySql database, which works fine for first three queries. But userId filter is not working, It should return entries with the matched UserId, but it is returning me all the records in that table. This is happening for both queries(Query of details and detailstwo table).
DELIMITER $$
DROP PROCEDURE IF EXISTS `sale`.`detailsProcedure` $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `detailsProcedure`(IN userId VARCHAR(100))
BEGIN
SELECT * FROM products WHERE ProductType=1 AND Price<=400;
SELECT * FROM products WHERE ProductType=1 AND Price<=700;
SELECT * FROM products WHERE ProductType=2;
SELECT * FROM products WHERE ProductType=3;
SELECT * FROM details WHERE UserId=userId;
SELECT * FROM detailsTwo WHERE UserId=userId;
END $$
DELIMITER
;
Seems like UserId is not getting compared or no filtration effect. Is there anything wrong with syntax. I looked into several post but didn't find particular solution which will help me,tried several way from stack overflow it self but problem persist.looking for help.
Note:- I am calling this procedure in my node.js restapi
Thanks In Advance!
Try this one:
DELIMITER $$
DROP PROCEDURE IF EXISTS `sale`.`detailsProcedure` $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `detailsProcedure`(IN v_userId VARCHAR(100))
BEGIN
SELECT * FROM products WHERE ProductType=1 AND Price<=400;
SELECT * FROM products WHERE ProductType=1 AND Price<=700;
SELECT * FROM products WHERE ProductType=2;
SELECT * FROM products WHERE ProductType=3;
SELECT * FROM details WHERE UserId=v_userId;
SELECT * FROM detailsTwo WHERE UserId=v_userId;
END $$
DELIMITER ;
Seems there was confusion in all the userId variations.

Selecting all values from a table in mysql using a stored procedure

I have a table called Contacts with a field called person_id that I have connected to a java application.
If no value is specified for person_id in the application, I want to select everything from the contacts table using a stored procedure.
The operation I want to perform is this:
Select * from Contacts where (person_id like "%")
For this I have written a stored procedure shown below:
Delimiter $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `selectTest2`(In p_id int(11))
BEGIN
if p_id = null then
set p_id = "%";
end if;
select * from Contacts where (person_id like p_id);
END $$
Delimiter ;
However when I run this procedure in my sql using the following
call selectTest2(null)
The table that is returned is blank. How do I make it show all the values in the table?
The parameter p_id gets its value from a text box in the application. If the user has entered an id, I want the procedure to show only that particular record else I want it to show all records.
What have I done wrong and how do I correct it? I am aware that p_id is an int however I tried the same thing with other fields of type varchar and the table failed to return any value.
Try using case statement in where clause like below
WHERE CASE WHEN p_id IS NOT NULL THEN person_id = p_id ELSE TRUE END
Hope this should solve your problem

MySQL Procedure within a Select?

I have a procedure that works like this:
mysql> call Ticket_FiscalTotals(100307);
+---------+--------+----------+------------+------------+
| Service | Items | SalesTax | eTaxAmount | GrandTotal |
+---------+--------+----------+------------+------------+
| 75.00 | 325.00 | 25.19 | 8.00 | 433.19 |
+---------+--------+----------+------------+------------+
1 row in set (0.08 sec)
I would like to call this procedure from within a select, like so:
SELECT Ticket.TicketID as `Ticket`,
Ticket.DtCheckOut as `Checkout Date / Time`,
CONCAT(Customer.FirstName, ' ', Customer.LastName) as `Full Name`,
Customer.PrimaryPhone as `Phone`,
(CALL Ticket_FiscalTotals(Ticket.TicketID)).Service as `Service`
FROM Ticket
INNER JOIN Customer ON Ticket.CustomerID = Customer.CustomerID
ORDER BY Ticket.SiteHomeLocation, Ticket.TicketID
However I know that this is painfully wrong. Can someone please point me in the proper direction? I will need access to all of the columns from the procedure to be (joined?) in the final Select. The SQL code within that procedure is rather painful, hence the reason for it in the first place!
The Ticket_FiscalTotals procedure returns a data set with some fields, but you need just one of them - Service. Rewrite your procedure to stored function - Get_Ticket_FiscalTotals_Service.
Another way is to create and fill temporary table in the procedure, and add this temporary to a query, e.g.:
DELIMITER $$
CREATE PROCEDURE Ticket_FiscalTotals()
BEGIN
DROP TEMPORARY TABLE IF EXISTS temp1;
CREATE TEMPORARY TABLE temp1(
Service FLOAT(10.2),
Items FLOAT(10.2),
SalesTax FLOAT(10.2),
eTaxAmount FLOAT(10.2),
GrandTotal FLOAT(10.2)
);
INSERT INTO temp1 VALUES (75.0, 325.0, 25.19, 8.0, 433.19);
END
$$
DELIMITER ;
-- Usage
CALL Ticket_FiscalTotals();
SELECT t.*, tmp.service FROM Ticket t, temp1 tmp;
You can't join directly to stored procedure. You can join to temporary table that this stored procedure fills:
create temporary table,
execute SP that fills data in your temp table,
join to temp table in your query,
drop temp table.
Of course it is not one line solution.
The other way (worse in my opinion) I think of is to have as many UDF as columns in SP result set, this might look like fallowing code:
SELECT
Ticket.TicketID as `Ticket`,
Ticket.DtCheckOut as `Checkout Date / Time`,
CONCAT(Customer.FirstName, ' ', Customer.LastName) as `Full Name`,
Customer.PrimaryPhone as `Phone`,
Ticket_FiscalTotals_Service(Ticket.TicketID) as `Service`,
Ticket_FiscalTotals_Items(Ticket.TicketID) as `Items`,
Ticket_FiscalTotals_SalesTax(Ticket.TicketID) as `SalesTax`,
Ticket_FiscalTotals_eTaxAmount(Ticket.TicketID) as `eTaxAmount`,
Ticket_FiscalTotals_GrandTotal(Ticket.TicketID) as `GrandTotal`
FROM Ticket
INNER JOIN Customer ON Ticket.CustomerID = Customer.CustomerID
ORDER BY Ticket.SiteHomeLocation, Ticket.TicketID

Getting "There is already an object named" while creating a temp table

Msg 2714, Level 16, State 1, Procedure QOTD, Line 12 There is already an object named '#tmpID3' in the database.
ALTER PROCEDURE QOTD (#source INT) AS
BEGIN
IF #source = 1
SELECT ID INTO #tmpID3 FROM tbl1
ELSE
SELECT ID INTO #tmpID3 FROM tbl2
SELECT ID FROM #tmpID3
DROP TABLE #tmpID3
END
Msg 2714, Level 16, State 1, Procedure QOTD, Line 7 There is already an object named '#tmpID3' in the database. – jesvin Nov 19 at 5:37
while adding this i am getting the error
You are seeing a parser error when trying to create your procedure. The temp table does not yet exist but the parser thinks it does.
Have a look at my answer to this question: There is already an object named '#columntable' in the database.
I originally thought, as others who have answered your question, that you would get this error because you were not explicitly dropping the temp table at the end of you procedure. However, as crokusek first pointed out in his comment:
local temp tables are auto deleted at the end of the procedure in
which they are created
So I tried creating your procedure in my SQL Server 2008 instance and got the same error.
Changing the procedure to use different temp table names, as shown below, avoids the problem and proves the temp tables are dropped after the procedure ends.
CREATE TABLE tbl1 ( ID INT )
GO
CREATE TABLE tbl2 ( ID INT )
GO
INSERT INTO tbl1(ID) VALUES (1),(2),(3)
INSERT INTO tbl2(ID) VALUES (4),(5),(6)
GO
CREATE PROCEDURE QOTD ( #source INT )
AS
SET NOCOUNT ON
BEGIN
IF #source = 1
BEGIN
SELECT ID INTO #tmpID13 FROM tbl1
SELECT ID FROM #tmpID13
END
ELSE
BEGIN
SELECT ID INTO #tmpID23 FROM tbl2
SELECT ID FROM #tmpID23
END
END
GO
EXEC QOTD 1
EXEC QOTD 2
Output:
ID
-----------
1
2
3
ID
-----------
4
5
6
It's already there. If you're creating this table as part of a regularly running script, add a DROP TABLE #tmpID3 at the start.
temp tables are single threaded (ie the server can do nothing else while creating it). If you're using it often, consider table variables instead.
Start procedure QOTD with:
Drop Table #tmpID3
Objects have to have unique names across the database. SQL Server handles the uniqueness of temporary table names. However, if there are supplementary objects, such as separately created primary keys, it is possible for collisions to occur when two users attempt to create the table at the same time.
The error message you cite has an object with ID in its name, so I am guessing this is the situation you find yourself in. Andy Novick has written a note on this topic, explaining why it might happen and giving a couple of workarounds. Check it out.
Have a look at Check If Temporary Table Exists
EDIT How to check for the temp table and drop it if it exists
IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL
BEGIN
DROP TABLE #TEMP
END
EDIT 2 It would seem that the 2 select into's are conflicting with each other. Creating the table before hand works though. Something like
ALTER PROCEDURE QOTD (#source INT)
AS
BEGIN
IF OBJECT_ID('tempdb..#tmpID3') IS NOT NULL
BEGIN
DROP TABLE #tmpID3
END
CREATE TABLE #tmpID3(
ID INT
)
IF #source = 1
BEGIN
INSERT INTO #tmpID3 SELECT ID FROM tbl1
END
ELSE
BEGIN
INSERT INTO #tmpID3 SELECT ID FROM tbl2
END
SELECT ID FROM #tmpID3
DROP TABLE #tmpID3
END
EDIT 3 the temp table is not required in this instance. A simple if will do
Something like
ALTER PROCEDURE QOTD (#source INT)
AS
BEGIN
IF #source = 1
BEGIN
SELECT ID FROM tbl1
END
ELSE
BEGIN
SELECT ID FROM tbl2
END
END
I had exactly the same issue, see my answer here:There is already an object named '#columntable' in the database
The solution in this case seems to be to first create the table, then add the rows. This way the parser does not complain (as this is a known parser issue).
ALTER PROCEDURE QOTD (#source INT) AS
BEGIN
-- Create the table without having to declare any column types or sizes
SELECT TOP 0 ID INTO #tmpID3 FROM tbl1
-- Prevent IDENTITY_INSERT error
SET IDENTITY_INSERT #tmpID3 ON
-- Add the actual rows required
IF #source = 1
INSERT INTO INTO #tmpID3 (ID) SELECT ID FROM tbl1
ELSE
INSERT INTO INTO #tmpID3 (ID) SELECT ID FROM tbl2
SET IDENTITY_INSERT #tmpID3 OFF
SELECT ID FROM #tmpID3
DROP TABLE #tmpID3
END