I have been working on a pretty large database this last week. Basically I am taking an Access database and converting it to a MySQL database. I have seccessfully converted all the tables and views to MySQL. However I have a view that requires input from the user, the date. The other view is the view that will be call.
view 1 - compiled_fourweeks - needs date
view 2 - metrics_fourweeks - uses `compiled_fourweeks in query.
I was thinking of a precedure but I won't be able to reference the columns in the query.
I am kind of running out of ideas at this point.
If I understand correctly, you need to execute a view (metrics_fourweeks) that needs data from another view (compiled_fourweeks), and this last view requires input from the user.
I would go with the procedure approach:
create procedure fourWeeksData(d date)
create or replace view compiled_fourweeks
select ...
from ...
where recordDate = f -- Just an example; use whichever where clause you need
...;
select * from metrics_fourweeks;
end
If your database will be used just by a single user, your problem is solved. But if your database is meant to be used by more than one user... well, you can use temporary tables:
create procedure fourWeeksData2(d date)
drop table if exists temp_compiled_fourweeks;
create temporary table temp_compiled_fourweeks
select ...
from ...
where recordDate = f -- Just an example; use whichever where clause you need
...;
-- You will need to create the required indexes for this new temp table
-- Now replicate the SQL statement, using your new temp table
select ...
from temp_compiled_fourweeks
...;
end
Hope this helps you.
Related
I am looking for some ideas or help on how I could make my query a little less resource intensive but I am not sure if there is an easier way to do what I am doing.
I have a search Store Proc that takes in a large number of parameters to search the database for different products. The user can search for multiple makes and models etc in the same search.
The way I work the search is the parameters are all organised and the call of the store procedure is produced and saved in the data base this is then called and the store procedure is executed and the results returned.
An example:
Make Ids selected : 1 ,2 ,3 ,4
Model IDs selected : 2,3,4
Proc call generated "Call my_store_prod ('1,2,3,4','2,3,4')"
This is saved in the database with a random string eg "wmF14ndfglq2p3yuMMM6cr" then this is used to call the store proc using $_Get['search_id'] www.site.com?search=wmF14ndfglq2p3yuMMM6cr
In the Store proc I then create some temp tables:
DROP TEMPORARY TABLE IF EXISTS tmp_manufacturer_id;
CREATE TEMPORARY TABLE tmp_manufacturer_id (manufacturer_id varchar(255));
/*MODEL_ID*/
DROP TEMPORARY TABLE IF EXISTS tmp_model_id;
CREATE TEMPORARY TABLE tmp_model_id (model_id varchar(255));
Then use a funtion to split the string of ids '1,2,3,4' and insert into the temp tables:
CALL sp_split(#manufacturer_id,'tmp_manufacturer_id');
/*MODEL_ID*/
CALL sp_split(#model_id,'tmp_model_id') ;
Then in the where clause I have something like this:
CASE WHEN #manufacturer_id = ''
THEN information_view.advert_id = information_view.advert_id
ELSE information_view.manufacturer_id IN (select * from tmp_manufacturer_id2)end
AND
CASE WHEN #model_id = ''
THEN information_view.advert_id = information_view.advert_id
ELSE information_view.model_id IN (select * from tmp_model_id2)end
This all is working fine but one of my problems is I need to return 7 Random "Featured" Adverts with the same search results.
The only that I have thought of is to do a UNION with the same query only with a
order by rand()
LIMIT 7
I was wondering if there would be an easier way to get my 7 random adverts without having to duplicate the whole query?
Any pointers for be really useful.
Server version: 5.7.37-log - MySQL Community Server (GPL)
Background - I have a DB created from a single large flat file. Instead of creating a single large table with 106 columns. I created a "columns" table which stores the column names and the id of the table that holds that data, plus 106 other tables to store the data for each column. Since not all the records have data in all columns, I thought this might be a more efficient way to load the data (maybe a bad idea).
The difficulty with this was rebuilding a single record from this structure. To facilitate this I created the following procedure:
DROP PROCEDURE IF EXISTS `col_val`;
delimiter $$
CREATE PROCEDURE `col_val`(IN id INT)
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp_record;
CREATE TEMPORARY TABLE tmp_record (id INT(11), val varchar(100)) ENGINE=MEMORY;
SET #ctr = 1;
SET #valsql = '';
WHILE (#ctr < 107) DO
SET #valsql = CONCAT('INSERT INTO tmp_record SELECT ',#ctr,', value FROM col',#ctr,' WHERE recordID = ',#id,';');
PREPARE s1 FROM #valsql;
EXECUTE s1;
DEALLOCATE PREPARE s1;
SET #ctr = #ctr+1;
END WHILE;
END$$
DELIMITER ;
Then I use the following SQL where the stored procedure parameter is the id of the record I want.
CALL col_val(10);
SELECT c.`name`, t.`val`
FROM `columns` c INNER JOIN tmp_record t ON c.ID = t.id
Problem - The first time I run this it works great. However, each subsequent run returns the exact same record even though the parameter is changed. How does this persist even when the stored procedure should be dropping and re-creating the temp table?
I might be re-thinking the whole design and going back to a single table, but the problem illustrates something I would like to understand.
Unsure if it matters but I'm running MySQL 5.6 (64 bit) on Windows 7 and executing the SQL via MySQL Workbench v5.2.47 CE.
Thanks,
In MySQL stored procedures, don't put an # symbol in front of local variables (input parameters or locally declared variables). The #id you used refers to a user variable, which is kind of like a global variable for the session you're invoking the procedure from.
In other words, #id is a different variable from id.
That's the explanation of the immediate problem you're having. However, I would not design the tables as you have done.
Since not all the records have data in all columns, I thought this might be a more efficient way to load the data
I recommend using a conventional single table, and use NULL to signify missing data.
Ok, First off, I am not a mysql guru. Second, I did search, but saw nothing relevant related to mysql, and since my DB knowledge is limited, guessing syntactical differences between two different Database types just isn't in the cards.
I am trying to determine if a particular value already exists in a table before inserting a row. I've decided to go about this using two Stored procedures. The first:
CREATE PROCEDURE `nExists` ( n VARCHAR(255) ) BEGIN
SELECT COUNT(*) FROM (SELECT * FROM Users WHERE username=n) as T;
END
And The Second:
CREATE PROCEDURE `createUser` ( n VARCHAR(255) ) BEGIN
IF (nExists(n) = 0) THEN
INSERT INTO Users...
END IF;
END
So, as you can see, I'm attempting to call nExists from createUser. I get the error that no Function exists with the name nExists...because it's a stored procedure. I'm not clear on what the difference is, or why such a difference would be necessary, but I'm a Java dev, so maybe I'm missing some grand DB-related concept here.
Could you guys help me out by any chance?
Thanks
I'm not sure how it helped you, but...
why SELECT COUNT(*) FROM (SELECT * FROM Users WHERE username=n) and not just SELECT COUNT(*) FROM Users WHERE username=n?
Just make the user name (or whatever the primary application index is) a UNIQUE index and then there is no need to test: Just try to insert a new record. If it already exists, handle the error. If it succeeds, all is well.
It can (and should) all be one stored procedure.
I'm really struggeling with this for some time now.
I have a MySQL database and a lot of data. It is a formula1 website i have to create for college.
Right now the j_tracks_rounds_results table is filled with data but one column is not filled out. It's the rank column.
I created a stored procedure as the following:
DROP PROCEDURE `sp_rank`//
delimiter ##
PROCEDURE `sp_rank`(sid INT)
begin
set #i = 0;
SELECT `performance`, subround_id, #i:=#i+1 as rank
FROM `j_tracks_rounds_results`
where subround_id = sid
order by `subround_id`,`performance`;
end
delimiter ;
The output is like the following:
rec.ID PERFORMANCE SUBROUND_ID RANK
87766 100,349114516829 1 1
93040 101,075635087628 1 2
88851 101,664302543497 1 3
It gets the results and ads a rank to it, sorted on performance so the lowest performance gets rank1 etc...
What i am trying to achieve is to put the rank back into the table. Like an ALTER command for the column "rank".
How would i be able to accomplish this?
Basically don't...
Create table to hold the key (rec.id ?) and the rank. Truncate it to get rid of the previous results then use insert into ... with your query and then join to it.
You really don't want to be altering tables in your normal running, guaranteed some one will use the column when it isn't there, and then when you look at the fault it will be...
People just don't look for table structures changing through the application lifetime, it's a screw up waiting to happen.
You are misapplying your SQL statements. You want the UPDATE command, not ALTER.
eg.
UPDATE table SET rank=#i WHERE subround_id=#id
I've recently moved from MSSQL to MySQL.
I would like to use a table variable (or equivalent) inside a MySQL 5.5 stored routine, to populate a dataset for an online report.
In MS SQL, I would do it this way
...
...
DECLARE #tblName TABLE
WHILE <condition>
BEGIN
Insert Row based on iteration value
END
...
...
From what I understand, I can't declare table variables in MySQL (correct me if I'm wrong) How do I implement the above logic in a MySQL stored procedure?
You could create a table or temporary table and populate it with data you need.
CREATE TABLE Syntax
You understand that limitation correctly. The MySQL user manual clearly states that user-defined variables cannot refer to a table:
http://dev.mysql.com/doc/refman/5.5/en/user-variables.html
User variables are intended to provide data values. They cannot be used directly in an SQL statement as an identifier or as part of an identifier, such as in contexts where a table or database name is expected, or as a reserved word such as SELECT.
create temporary table tmp
(
id int unsigned not null,
name varchar(32) not null
)
engine=memory; -- change engine type if required e.g myisam/innodb
insert into tmp (id, name) select id, name from foo... ;
-- do more work...
select * from tmp order by id;
drop temporary table if exists tmp;
I think this covers it. Also, this may be helpful.