Joining a table stored within a column of the results - mysql

I want to try and keep this as one query and not use PHP, but it's proving to be tough.
I have a table called applications, that stores all the applications and some basic information about them.
Then, I have a table with all the types of applications in it, and that table contains a reference to another table which stores more specific data about the specific type of application in question.
select applications.id as appid, applications.category, type.title as type, type.id as tid, type.valuefld, type.tablename
from applications
left join type on applications.typeid=type.id
left join department on type.deptid=department.id
where not isnull(work_cat)
and work_cat != ''
and applications.deleted=0
and datei between '10-04-14' and '11-04-14'
order by type, work_cat
Now, in the old version, there is another query on every single result. Over hundreds of results... that sucks.
This is the query I'd like to integrate so I can get all the data in one result row. (Old is ASP, I'm re-writing it in PHP)
query = "select sum("&adors.fields("valuefld")&") as cost, description from "&adors.fields("tablename")&" where appid = '"&adors.fields("tablename")&"'"
Prepared statements, I'm aware, are the best solution, but for now they are not an option.

You can't do this with a plain SQL query - you need to have a defined set of tables that your query is based on. The fact that your current implementation queries from whatever table is named by tablename from the first result-set means that to get this all in one query, you will have to restructure your data. You have to know what tables you're querying from rather than having it dynamic.
If the reason for these different tables is the different information stored in each requiring different record (column) structures, you might want to look into Key/Value pair storage in a large table. Once you combine the dynamically named ones into a single location you can integrate your two queries together.

Related

sql query not returning non-unique value in table

I have a MySQL database for an investor to track his investments:
the 'deal' table has info about the investments, including different categories for the investment (asset_class).
Another table ('updates') tracks updates on a specific investment (investment name, date, and lots of financial details.)
I want to write a query that allows the user to select all updates from 'updates' under a specific asset_class. However, as mentioned, asset_class is in the investment table. I wrote the following query:
SELECT *
FROM updates
WHERE updates.invest_name IN (SELECT deal.deal_name
FROM deal
WHERE deal.asset_class = '$asset_class'
);
I'm using PHP, so $asset_class is the selected variable of asset_class.
However, the query only returns unique update names, but I want to see ALL updates for the given asset_class, even if several updates are made under one investment name.
Any advice? Thanks!
Your query should do what you intend. In general, though, this type of query would be written using a JOIN. More importantly use parameter placeholders instead of munging query strings:
SELECT u.*
FROM updates u JOIN
deal d
ON u.invest_name = d.deal_name
WHERE d.asset_class = ?;
This can take advantage of indexes on deal(asset_class, deal_name) and updates(invest_name).
The ? represents a parameter that you pass into the query when you run it. The exact syntax depends on how you are making the call.

Storing SQL queries in table and run them on-the-fly when selecting - Possible? Good practice?

I'm currently thinking about a database schema in MySQL where I store SELECT queries into a certain table column, just to execute them on-the-fly when getting selected, and having the result passed instead of the actual query.
Would this be possible somehow? Or may this be bad practice? Is it even technically possible to have a result table passed to a single field, at least so I could run the query through PDO to get back a nested result array? Are there any alternatives?
I've read that this may be achieved through stored procedures, and although I grip the concept of those I can't think of how I could use those to achieve that.
You could do this, but what purpose do you have for doing it?
I would suggest using views:
The syntax should be valid when the view is created, unlike storing
the SQL in a field which may have invalid syntax.
It's easier to debug and modify.
For example, let's say one of the queries you want to store is:
SELECT product_category, COUNT(*) AS category_count
FROM product
GROUP BY product_category;
You can create a new "view" object that defines this query:
CREATE VIEW prod_cat_count AS
SELECT product_category, COUNT(*) AS category_count
FROM product
GROUP BY product_category;
Now, the object called "prod_cat_count" is stored in the database. Internally, the database just knows that "prod_cat_count" is equal to the SELECT query we mentioned. When the view is created, the database validates the syntax (checks that all columns exist, checks you haven't forgotten the GROUP BY, for example)
Then, whenever you want to get this data/run this query, you can run this statement (in SQL or in application code, for example):
SELECT product_category, category_count
FROM prod_cat_count;
If you then decide you want to change the way the product categories are counted, you can adjust the view:
SELECT product_category, COUNT(*) AS category_count
FROM product
GROUP BY product_category
ORDER BY product_category;
Hope that helps!

How do the fields in "SHOW COLUMNS" command map to specific tables?

Here is a View called viewwithcommonfield :
SELECT
`schematopologytest01`.`talpha`.`CommonField` AS `CommonField_tAlpha`,
`schematopologytest01`.`tbeta`.`CommonField` AS `CommonField_tBeta`
FROM
(`schematopologytest01`.`talpha`
JOIN `schematopologytest01`.`tbeta`)
When I execute
SHOW FULL fields FROM viewwithcommonfield IN SchemaTopologyTest01
I get this:
How do I map the fields back to specific tables? Can I write a view against the tables in information_schema?
Here are the table structures that are referenced in the view. The tables share a common field called CommonField:
No, there is no metadata available to map views of a column back to the original column in a base table. That would require multiple tables, because any given expression in the select-list may reference multiple columns from different tables.
Consider:
SELECT CONCAT(
`schematopologytest01`.`talpha`.`AlphaFieldA`,
`schematopologytest01`.`tbeta`.`BetaFieldE`) AS `ConcatenatedField`
FROM `schematopologytest01`.`talpha`
JOIN `schematopologytest01`.`tbeta` ON ...
Which table and column would ConcatenatedField list as its origin? It would have to be stored in two rows of another INFORMATION_SCHEMA table.
There are also select-list expressions possible in a view that don't reference any base table:
CREATE VIEW ViewNow AS SELECT NOW() AS `now`;
What about columns that are themselves scalar subqueries? Or references to stored functions? Or an aggregate function like COUNT() or SUM() where the value is not found in any base table?
Many views do not derive their data from base tables deterministically at all. Edit: What I mean is that it's not always possible to know which rows or columns are the source of data in a view, because they results are combined in some ways. It's probably more clear to say that reversing the query to get the original data is not always possible, depending on the query.
It's not possible to update those views. But if there were metadata about where the data "came from," there would have to be something in the metadata to indicate that. It would be impractical because it would be complex, and have little value.

SQL Filtering and Replacing

I have a few tables in SQL that require content filtering, primarily for profanity. I want to allow my application(s) to insert data they want and have the server replace any profanity with asterisks such that I do not need to implement filtering on a variety of platforms.
I know triggers could be used for future, however, I am trying to determine the most efficient way to complete this task.
Here are some details:
There are 2 tables I need to ensure has content filtering as they are public facing: feedback and users. Here are the particular fields:
Table -> Fields
Feedback -> Subject, Message
Users -> Firstname, Lastname, Alias
I am relatively new to MySQL and know that having a table of values to replace may be the easiest-to-modify option.
My question is:
How would I join 2 tables and replace particular chars with asterisks using key words located in a third table?
I have these queries so far to locate the columns of interest, just not sure how to incorporate the replacement function and the ability to check both at the same time:
SELECT u.firstname, u.lastname, u.username FROM users u, feedback f, terms t;
SELECT f.subject, f.message FROM feedback f;
You are better off creating a new column (named alias or similar) and storing values with asterisks in there than writing a SELECT query and performing find-replace. Following are the advantages:
Handling this scenario in trigger means you will only perform this operation when a record gets inserted or updated, whereas in SELECT query, each read will need replacing.
You can't really use join here because (a) each value of feedback and user table needs to be compared with all the values of terms table and (b) this needs to be performed for all the columns that might contain these words. So, it's more of a use case for cursor than join.

Advantage of using Views in MySQL

I've learned that views can be used to create custom "table views" (so to say) that aggregate related data from multiple tables.
My question is: what are the advantages of views? Specifically, let's say I have two tables:
event | eid, typeid, name
eventtype | typeid, max_team_members
Now I create a view:
eventdetails | event.eid, event.name, eventtype.max_team_members
| where event.typeid=eventtype.typeid
Now if I want to maximum number of members allowed in a team for some event, I could:
use the view
do a join query (or maybe a stored procedure).
What would be my advantages/disadvantages in each method?
Another query: if data in table events and eventtypes gets updated, is there any overhead involved in updating the data in the view (considering it caches resultant data)?
A view is not stored separately: when you query a view, the view is replaced with the definition of that view. So and changes to the data in the tables will show up immediately via the view.
In addition to the security feature pointed out earlier:
If you're writing a large number of queries that would perform that join, it factors out that SQL code. Like doing some operations in a function used in several places, it can make your code easier to read/write/debug.
It would also allow you to change how the join is performed in the future in one place. Perhaps a 1-to-many relationship could become a many-to-many relationship, introducing an extra table in the join. Or you may decide to denormalize and include all of the eventtype fields in each event record so that you don't have to join each time (trading space for query execution time).
You could further split tables later, changing it to a 3-way join, and other queries using the view wouldn't have to be rewritten.
You could add new columns to the table(s) and change the view to leave out the new columns so that some older queries using "select *" don't break when you change the table definitions.
You can restrict users to the view instead of the underlying table(s), thereby enhancing security.
Advantages of SQL Views
1). You can save a complex query(a query with join multiple tables) as view to reuse it in simple manners.
In other words, you can change your multi-line query into single-line query.
2). You can hide sensitive data by converting your query into view with new name and can give the access only required columns instead of giving the access of actual table.