Passing part of table name to query - mysql

I have a database that keeps a table logs - each log id will be numeric
There are matching tables to join on that are NAMED log + the numeric logId
I need to be able to join these tables based on a log id that will be passed
ex:
SELECT * from ACTIVITIES a
INNER JOIN (LOG + LogID) l2 ON a.activityID = l2.activityID
The 'logID' will be passed as a paramater
SO if logID is 100 I am looking for table log100
How can I do this?

SQL requires that table names be fixed before you pass the query to prepare(). You can't use a parameter for the table name. Not part of the table name, nor the whole table name.
So you must form the table name in a variable in your application code and then use that variable in the SQL query.
Example (pseudocode, like PHP):
$logid = 100;
$tablename = "log{$logid}";
$sql = "SELECT * from ACTIVITIES a INNER JOIN `{$tablename}` l2 ON a.activityID = l2.activityID";
$stmt = $dbh->prepare($sql);
I'd encourage you to check out MySQL's table partitioning feature. You may be able to avoid having so many log tables, and just treat them as individual partitions within one whole table.

you have to use a dynamic sql statement in order for you to execute queries on dynamic tables.
having the log ID as the parameter, create a stored proc accepting one parameter:
CREATE PROCEDURE usp_GetTableLogs
#logID int
as
DECLARE
#select varchar(2000)
SET #select = 'SELECT * from ACTIVITIES a INNER JOIN LOG' + #logID + ' l2 ON a.activityID = l2.activityID'
EXECUTE (#select)
:)

Related

How to use variables column name in where clause MySQL?

In this query:
SELECT *
FROM general_settings AS general_settings
JOIN settings_attribute AS settings_attribute ON settings_attribute.id = general_settings.settings_attribute_id
JOIN user_settings AS user_settings ON general_settings.user_settings_id = user_settings.id
WHERE
(settings_attribute.name = 'AAA' AND brand_settings.AAA <> general_settings.value)
OR
(settings_attribute.name = 'BBB' AND brand_settings.BBB <> general_settings.value)
OR
(settings_attribute.name = 'CCC' AND brand_settings.CCC <> general_settings.value)
;
I want a way using MySQL or Redshift to use settings_attribute.name as column name to avoid writing all the attribute names as a static in the query,
for example like this:
SELECT *
FROM general_settings AS general_settings
JOIN settings_attribute AS settings_attribute ON settings_attribute.id = general_settings.settings_attribute_id
JOIN user_settings AS user_settings ON general_settings.user_settings_id = user_settings.id
WHERE
brand_settings.#settings_attribute.name <> general_settings.value
;
No, this is not possible. In SQL, all identifiers (e.g. column names) must be explicit and fixed in the query at the time it is parsed, so the SQL engine can verify that the columns actually exist before it begins executing. It's not possible for a query to name different columns based on the string values it reads during execution.
What would happen if your settings_attribute.name contained 'XYZ' in some row, but there was no column by that name? It would be an error if you named a column that didn't exist, but in SQL that is checked at the time the query is parsed.

Passing result of one table to another table in Database?

I have the following scenario: I am trying to pass result of one query to another , In this case I am trying to pass view_id in another query since this are ids they are unique and cant be duplicate in any case .
select view_id from view where view_query_id = "18711987173"
select queue_id from queue where queue_view = view_id
`
I saw some examples and I tried executing them something like as
select view_id from view where view_query_id = "18711987173 exists (select queue_id from queue where queue_view = view.view_id)
But surely this didnt helped :)
You can use a common table expression
WITH temp AS (SELECT view_id FROM view WHERE view_query_id = "18711987173")
SELECT queue_id FROM queue q INNER JOIN temp t ON q.queue_id = t.view_id;
This should work regardless of what relationship is between those tables. You can replace the JOIN by WHERE..IN, but this way seems cleaner and takes care if the no. of values in IN becomes too large.
Use table expression
WITH temp AS (SELECT view_id FROM view WHERE view_query_id = "18711987173")
SELECT queue_id FROM queue q INNER JOIN temp t ON q.queue_id = t.view_id;

Combine SQL query for userID with separate query for 2nd table

I'm trying to create an SQL query which filters information by customerID in one table and then combine that with information in another table. I have this query which filters by customerID
$query = mysqli_query($connection, "
SELECT *
FROM booked_activities
WHERE customerID LIKE $_SESSION[customerID]
");
/* INNER JOIN activities ON booked_activities.activityID = activities.activityID);*/
The second part I commented out is where I tried to combine the first half of the query with another table.
The activityID is a common ID in tables: booked_activites and activities.
Right now I can output the first query as activityID but I need to use the activityID to output the activityName from the activities table.
have you tried
$query = mysqli_query($connection, "SELECT *,ac.activityName FROM booked_activities INNER JOIN activities ac ON booked_activities.activityID = activities.activityID
WHERE customerID LIKE $_SESSION[customerID] );
also I would suggest using prepared statement for passing custometr id, instead of using sesstion variable directly in string.
SELECT * FROM booked_activities t1
join activities t2 on t2.activityID = t1.activityID
WHERE t1.customerID LIKE $_SESSION[customerID]

How can I show datas not in table with out compairing with other tables in sql

I have one table named FILEINFO. Daily some file_names(around 100) will come. I need to check whether the names are present in the table or not. in a single query
Thanks in advance
I don't know if this fits in with your data pipeline, but one clean approach here would be to write those new incoming file names into some sort of table (temporary or permanent), and then use a simple exists query to check if they are already present in your current table, e.g.
SELECT filename AS new_file
FROM temp_names t1
WHERE NOT EXISTS (SELECT 1 FROM FILEINFO t2 WHERE t2.filename = t1.filename);
If you wanted to insert only new file names, you could use similar logic, e.g.
INSERT INTO FILEINFO (filename)
SELECT filename
FROM temp_names t1
WHERE NOT EXISTS (SELECT 1 FROM FILEINFO t2 WHERE t2.filename = t1.filename);
The other approach would be without using a temporary table (Tim Biegeleisen answer).
This approach will only use one query
SELECT
FILEINFO.filename
FROM (
SELECT 'filename1' AS filename FROM DUAL
UNION
SELECT 'filename2' AS filename FROM DUAL
) AS file_names
LEFT JOIN
FILEINFO
ON
file_names.filename = FILEINFO.filename
WHERE
FILEINFO.filename IS NULL
This query should also work in both MySQL and Oracle database.
Both database systems are using DUAL as a "dummy" table to allow tableless SELECTS

Why does my indexed column appear not to have statistics?

I'm using SQL Server and I'm currently trying to debug some queries where the optimizer has chosen a poor execution plan and I noticed for one of my indexed columns that when I run the command:
DBCC SHOW_STATISTICS ("tablename", columnname);
for this indexed column, the database returns:
Could not locate statistics 'columnname' in the system catalogs.
According to this page:
http://msdn.microsoft.com/en-us/library/ms190397.aspx
"The query optimizer creates statistics for indexes on tables or views when the index is created."
I also have AUTO_CREATE_STATISTICS on.
Should I have to manually have to run a CREATE STATISTICS for this column? If so, since it's an index shouldn't it already have statistics for the column?
From https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-show-statistics-transact-sql:
If target is the name of an existing column, and an automatically
created statistics on this column exists, information about that
auto-created statistic is returned. If an automatically created
statistic does not exist for a column target, error message 2767 is
returned.
So specifying the name of the index for target (the second parameter) will work, but it won't work if you use the column name.
If you run this (credit to Erland Sommarskog, http://www.sommarskog.se/query-plan-mysteries.html), you can see if stats were auto-created or not:
DECLARE #tbl NVARCHAR(256)
SELECT #tbl = 'tableName'
SELECT
o.name, s.stats_id, s.name, s.auto_created, s.user_created,
SUBSTRING(scols.cols, 3, LEN(scols.cols)) AS stat_cols,
STATS_DATE(o.object_id, s.stats_id) AS stats_date,
s.filter_definition
FROM
sys.objects o JOIN
sys.stats s ON s.object_id = o.object_id
CROSS APPLY
(
SELECT ', ' + c.name
FROM
sys.stats_columns sc JOIN
sys.columns c ON sc.object_id = c.object_id AND sc.column_id = c.column_id
WHERE sc.object_id = s.object_id AND sc.stats_id = s.stats_id
ORDER BY sc.stats_column_id
FOR XML PATH('')
) AS scols(cols)
WHERE o.name = #tbl
ORDER BY o.name, s.stats_id