How to create a central parameter, like Report-Date? - sql

I would like to create one location on sql server where I store the report-date and all queries and procedures should relate to this one value.
In that way I only have to change the report date on one location and it is valid for all related queries and procedures.
I started with a scalar function that retrieves a value from a table, but this slows down the queries enomoursly.
I tried an inline table valued function, but have no idea how to include this into a query.
I tried with a table that contains the report-date and used a cross join.
But it says:
The multi-part identifier could not be bound
Maybe some of you have an idea what to do here?

One possibility is to create a table, let's say TblReportDate with two columns: id and reportDate.
Then add one row with id 1 like following:
+----+------------+
| id | reportDate |
+----+------------+
| 1 | 04.04.2018 |
+----+------------+
Now join the table with a LEFT JOIN and use the >= operator to compare with the id-column of the main-table:
SELECT * FROM mainTable
LEFT JOIN TblReportDate ON mainTable.id >= TblReportDate.id

Related

SQL query to override content of column when matched column

Please who can help with this scenario?
I have two tables, both they have a common column ID, and Table 1 has a column Title. Normally I should update the content of this Title column for some ID, but since the table was already in use somewhere else, it wasn't a good idea to change data directly in Table 1.
That's why I created a new table table 2, which hold only the Title that must be changed associated with these ID that must be changed.
Now I am trying to get these updated titles from table 2, when there is a matching ID in table 1, otherwise show only the contents of table 1.
The result should be something like that but without using If statements.
__ID__ Title
| | | |
| | | |
You can use LEFT OUTER JOIN to this new table and COALESCE() function to say "If there is data in the new table, use it, otherwise use the data in the existing table" . Something like:
SELECT t1.id, COALESCE(t2.title, t1.title) as title
FROM t1
LEFT OUTER JOIN t2 ON t1.id = t2.id;

SELECT the FROM table with a sub select and modify the resulting table name

I have the follwing given two tables which can not be changed.
1: DataTypes
+----------------------+-----------------------+
| datatypename(String) | datatypetable(String) |
+----------------------+-----------------------+
Example data:
+-----------+------------+
| CycleTime | datalong |
+-----------+------------+
| InjTime1 | datadouble |
+-----------+------------+
2: datalong_1 (data model does not matter here)
I want to make a query now that reads the datatypetable attribute from the datatypes table, adds the String "_1" to it and selects all content from it.
I imagined it, from a programmatic perspective, to look something similar to this statement which obviously doesn't work yet:
SELECT * FROM
(SELECT datatypetable FROM datatypes WHERE datatypename = 'CycleTime') + '_1'
How can I make this happen in SQL using HSQLDB?
Thanks to Leonidas199x I know now how to get in the '_1' in but how do I tell the FROM statement that the subselect is not a new table I want to read from but instead the name of an existing table I want to read from.
SELECT * FROM
(SELECT RTRIM(datatypetable)+'_1' FROM datatypes WHERE datatypename = 'CycleTime')
According to this question which is identical to mine this is not possible:
using subquery instead of the tablename
:(
Can you explain your data model in a little more detail? I am not sure I understand exactly what it is you are looking to do.
If you are wanting to add _1 to the 'datatypename', you can use:
SELECT datatypename+'_1'
FROM datatypes

How to build virtual columns?

Sorry if this is a basic question. I'm fairly new to SQL, so I guess I'm just missing the name of the concept to search for.
Quick overview.
First table (items):
ID | name
-------------
1 | abc
2 | def
3 | ghi
4 | jkl
Second table (pairs):
ID | FirstMember | SecondMember Virtual column (pair name)
-------------------------------------
1 | 2 | 3 defghi
2 | 1 | 4 abcjkl
I'm trying to build the virtual column shown in the second table
It could be built at the time any entry is made in the second table, but if done that way, the data in that column would get wrong any time one of the items in the first table is renamed.
I also understand that I can build that column any time I need it (in either plain requests or stored procedures), but that would lead to code duplication, since the second table can be involved in multiple different requests.
So is there a way to define a "virtual" column, that could be accessed as a normal column, but whose content is built dynamically?
Thanks.
Edit: this is on MsSql 2008, but an engine-agnostic solution would be preferred.
Edit: the example above was oversimplified in multiple ways - the major one being that the virtual column content isn't a straight concatenation of both names, but something more complex, depending on the content of columns I didn't described. Still, you've provided multiple paths that seems promising - I'll be back. Thanks.
You need to join the items table twice:
select p.id,
p.firstMember,
p.secondMember,
i1.name||i2.name as pair_name
from pairs as p
join items as i1 on p.FirstMember = i1.id
join items as i2 on p.SecondMember = i2.id;
Then put this into a view and you have your "virtual column". You would simply query the view instead of the actual pairs table wherever you need the pair_name column.
Note that the above uses inner joins, if your "FirstMember" and "SecondMember" columns might be null, you probably want to use an outer join instead.
You can use a view, which creates a table-like object from a query result, such as the one with a_horse_with_no_name provided.
CREATE VIEW pair_names AS
SELECT p.id,
p.firstMember,
p.secondMember,
CONCAT(i1.name, i2.name) AS pair_name
FROM pairs AS p
JOIN items AS i1 ON p.FirstMember = i1.id
JOIN items AS i2 ON p.SecondMember = i2.id;
Then to query the results just do:
SELECT id, pair_name FROM pair_names;
You could create a view for your 'virtual column', if you wanted to, like so:
CREATE VIEW aView AS
SELECT
p.ID,
p.FirstMember,
p.SecondMember,
a.name + b.name as 'PairName'
FROM
pairs p
LEFT JOIN
items a
ON
p.FirstMember = a.ID
LEFT JOIN
items b
ON
p.SecondMember = b.ID
Edit:
Or, of course, you could just use a similar select statement every time.
When selecting from tables you can name the results of a column using AS.
SELECT st.ID, st.FirstMember, st.SecondMember, ft1.Name + ft2.Name AS PairName
FROM Second_Table st
JOIN First_Table ft1 ON st.FirstMember = ft1.ID
JOIN First_Table ft2 ON st.SecondMember = ft2.ID
Should give you something like what you are after.

Get data from one table using id and date ranges stored in another table

The app I am writing is for telemetry units that get rented out to customers, and I am trying to query logged data for a particular customer, without a customer_id_fk column in the Log table.
I have the following tables:
Customer table:
id | name | ...
Unit table:
id | name | ...
RentOut table:
id | start_date | end_date | unit_id_fk | customer_id_fk
Log table:
id | unit_id_fk | datetime | data1 | data2
The reason a customer_id_fk column is not included in the Log table is so that a mistake in the RentOut table is easily rectified, without the need to alter data in the Log table (though maybe there is a better way to do this?).
It would be more efficient to include the customer in the log table. But, without that, you can get what you want with a bunch of joins:
select l.*, c.*
from log l left outer join
RentOut ro
on l.unit_id_fk = ro.unit_id_rk and
l.datetime between ro.start_date and ro.end_date left outer join
Customer c
on ro.customer_id = c.id
where c.<whatever> = <foobar>
If the dates in the RentOut table are really dates (with no times), and the log records have a datetime, then you might have to do more date arithmetic for the join to work properly. For instance, you might need to say the "start" really is after noon and the "end" is really before noon, for a given log record.

PostgreSQL: How to optimize this query

I am developing a small application in C++ and using PostgreSQL as back-end database. Along with other tables in my database in have a "projects" table. Based on each primary key of this table a new table is dynamically added in my Database.
Example:
Suppose the projects table contains following 3 rows:
--------------------------------
| Id |Other Columns Goes here |
--------------------------------
| 1 | |
--------------------------------
| 2 | |
--------------------------------
| 3 | |
--------------------------------
So in this case i also have following three more table
Table1, Table2, Table3
Now you might notice that the table names are generated by appending projects.Id at the end of fixed string i.e "Table".
It might also be possible that for some projects no table is generated.
Example:
Suppose the projects table contains following 3 rows:
--------------------------------
| Id |Other Columns Goes here |
--------------------------------
| 1 | |
--------------------------------
| 2 | |
--------------------------------
| 3 | |
--------------------------------
So in this i might found only following two tables in my database:
Table1, Table3
Now i simply need to get all the valid projects. For this currently i am using following algo:
//part1
SELECT * FROM Projects Table
get the projects info one by one from the results of above query and store them in new instance of my Custom Class Project
Store the above instance in some contianer e.g Vector say vProjects
//part 2
For each Project p in vProject
if (TableExist(p.Id))
Store p in a new container say vValidatedProjects
Note: The TableExist() method execute the following query:
SELECT COUNT(*) FROM pg_tables WHERE tablename = 'Table"+ p.Id + "'"
Now every thing is working fine as expected but !!! the program executes very slow just because of the second part of above algo, if we have one thousand projects the TableExist() method is also called thousand time and each time this method is called a new query is executed which slow downs the program :(
The solution in my mind is some such thing
//part1
SELECT * FROM Projects Table
WHERE a table exist angainst projets.Id
get only those projects info for whom a dynamic table exist. From the results of above query and store them in new instance of my Custom Class Project
Store the above instance in some contianer e.g Vector say vProjects.
Now in this way only one query did the job for us rather than N+1 Queries (Where N is no of rows in Projects Table)
But i don't know how do i write such a query that returns the above results. Please help me in acheiving this.
Changing the design would be the best solution.
If that is not an option, then you could change the second part:
//part 2
For each Project p in vProject
if (TableExist(p.Id))
Store p in a new container say vValidatedProjects
Note: The TableExist() method execute the following query:
SELECT COUNT(*) FROM pg_tables WHERE tablename = 'Table"+ p.Id + "'"
by, first adding a new boolean column in projects table (lets name it projects.TableExists )
Then, run your current TableExist() function one and populate that column. In addition, chnage the code that creates table for a project, to also update that column and the code that deletes a table to also update the column accordingly.
Then your second part would be:
//part 2
For each Project p in vProject
if (p.TableExists)
Store p in a new container say vValidatedProjects
Note: The TableExist() method will not be used any more
I would rather have one table with project_id in it and do all selects with where project_id = .... That would result in better table statistics and the table optimizer will make a better job.