I have a database view which selects two columns from two different tables with the same name.
For example generating a DDL for the view would generate the following:
create view MYSCHEMA.VPRODUCTS ("Name", "AlternameName"...) AS
A.Name,
B.Name,
from PRODUCTSA A
left join PRODUCTSB B
...
When I run the command to generate a Liquibase change set, the SQL in the tag only contains a select statement for the two columns and makes no distinction for the unique column name (i.e. "Name", "AlternameName").
<createView viewName="VPRODUCTS ">SELECT
A.Name
,B.Name
from PRODUCTSA A
left join PRODUCTSB B
...
As a result, whenever I try to execute the change set Liquibase complains about duplicate entries for columns with the same name.
I can fix this by adding SQL "AS" statements in the tag, but I'd prefer if there was a better way to do this.
<createView viewName="VPRODUCTS ">SELECT
A.Name
,B.Name AS AlternateName
from PRODUCTSA A
left join PRODUCTSB B
...
Is there an attribute or tag that would allow me to specify the column names when creating the view, or providing the raw SQL in the DDL?
There isn't another way. Liquibase simply passes the nested SELECT statement into the create view statement so whatever is required in the select needs to be part of the query. There is no built-in pre-processing of the view statement beyond pre-pending "CREATE VIEW X"
If you want to provide the raw SQL you can always use the tag.
Another way would be to use subselects, like this:
SELECT [COLUMNLIST 1:1 RENAMED] FROM (your view)
Or use WITH blocks along the same line of thinking.
Related
I have a query like this:
Query 1:
select *
from items item
This is bind to an entity in SpringJPA.
Now I have to select one more column from another table like below.
Query 2:
select item.*,is.id
from items item
inner join item_state itm_s where item.id=itm_s.id
Now,there is a column "code" which exists in both item and item_state. I want to select it from item_state and not from item due to some data issues. I know the straight forward way is to write all columns in select statement,excluding code column from item and including code column from item_state.
But the thing is item table has around 100 columns.
Is there a good way to solve this issue without changing the entity class?
Look at Spring Data JPA projections and perform the following query:
#Query("select item.*, itm_s.code from items item join item.item_state itm_s where item.id = itm_s.id")
You will have to look at the resulting query to write your projection class.
In my webapp I need to create a query engine module where the user selects in the view what columns and filters he want and get the datas related to these queries.
So, I have to build SQL dynamic queries with this kind of format :
SELECT {columns} FROM MainTable FULL OUTER JOIN SecondTable ON ... FULL OUTER JOIN ThirdTable ON ... WHERE {filters}
The columns and filters are known at runtime. (read-only)
Actually, I have a big SQL Server view (Mapped entity in Java) which make 3 FULL OUTER JOIN of others SQL server views. And I build the query in the source code by parsing keywords as AND, OR, number, date, text, ...
Finally, I return a response in the front-end module a table with datas.
But, I'm facing performance issues (scalability) with this method and I'm looking for a more efficient way to do that.
Is it possible to split the SELECT query mentionned above in subqueries to improve performances ? Or there is better design approach for that ?
Here the request I actually use (names changed) with Hibernate :
SELECT * FROM BigView "+WHERE+" OPTION(ROBUST PLAN)
(BigView is aggregation of 4 views : RootTable, Table2, Table3, Table4)
Btw, I know "+WHERE+" is a bad practice but this is not the concern of this topic
I thought using this instead (delete BigView in SQL Server and the related entity) but it actually does same thing even if there is a little performance gain with the columns restriction :
SELECT ROW_NUMBER() OVER (ORDER BY id) AS rownum, tmp.* FROM ( SELECT '' AS id, "+columns+" "+
"FROM RootTable FULL OUTER JOIN "+
"Table2 ON RootTable.RT_ID = Table2.RT_N FULL OUTER JOIN "+
"Table3 ON RootTable.RT_ID = Table3.RT_ID FULL OUTER JOIN "+
"Table4 ON RootTable.RT_ID = Table4.RT_N "+
WHERE+" ) AS tmp
My previous deleted question was not enough focused so I hope this one is correct.
EDIT : I add this filter (WHERE clause) to show what can be requested for example :
RT_ID>'10' AND ( Table2_Topic LIKE '%test%' OR Table3_Date=CONVERT(datetime, '24/09/2020', 103) OR ( Table3_N is not null and Table2_ID<>0 ) )
I have JDBC Connection to my cloud MySQL database.
Utilizing the benefit of View's fetch time, I decided to create view for my user-queried searched results to be added into my JavaFX UI TableView.
I have following SQL View to run from method in UI.
CREATE VIEW `SEARCHED_QUERY_VIEW` AS
SELECT PRODUCTS.id,
PRODUCTS.name AS 'Product name',
MANUFACTURER.name AS 'Manufacturer name',
PACKAGE.name AS 'Package type',
SUB_PACKAGE.name AS 'Sub Package type'
FROM LOGISTICS.PRODUCTS
JOIN MANUFACTURER ON PRODUCTS.manid = MANUFACTURER.id
JOIN PACKAGE ON PRODUCTS.packageid = PACKAGE.id
JOIN SUB_PACKAGE ON PRODUCTS.subpackageid = SUB_PACKAGE.id
WHERE MANUFACTURER.name LIKE '%VIT%' OR PRODUCTS.name LIKE '%VIT%';
Now the problem lies with LIKE here.
I want LIKE to get an argument which will be passed from a parameterized method in JavaFX.
Can anybody advise solution on how to rework the view to receive custom LIKE parameter from Java Method?
You should move like parameter to select from the View.
So create the View without like condition but use LIKE in the query:
SELECT * FROM SEARCHED_QUERY_VIEW WHERE `Manufacturer name` LIKE '%VIT%' OR `Product name` LIKE '%VIT%';
I am trying to select one row from all 3 tables. The tables have the same structure, 4 columns, "code", "airportname", "latitude", "longitude".
The query I am trying to write is:
select
finnairroute.code,finnairroute.airportname,finnairroute.latitude,finnairroute.longitude,lhroute.airportname,lhroute.latitude,lhroute.longitude,sasroute.code,sasroute.airportname,sasroute.latitude,sasroute.longitude
FROM frs.sasroute, frs.finnairroute,frs.lhroute where
sasroute.code="BER" or finnairroute.code ="BER" or lhroute.code
="BER";
Tested with Mysql workbench and I got this result:
How should I write the query in order to get one single row that has all the info for "BER"?
Many thanks!
You can try something like this:
SELECT finnairroute.*,lhroute.*,sasroute.* FROM DUAL
LEFT OUTER JOIN finnairroute ON (finnairroute.code='BER')
LEFT OUTER JOIN lhroute ON (lhroute.code='BER')
LEFT OUTER JOIN sasroute ON (sasroute.code='BER')
The thing is that you will always get one row, even if the code is in none of the table. You need to test whether finnairroute.code, lhroute.code and sasroute.code are null or not.
Another way to approach the problem:
SELECT 'finnair' as company,code,airportname,latitude,longitude FROM finnairroute WHERE code='BER'
UNION SELECT 'lh' as company,code,airportname,latitude,longitude FROM lhroute WHERE code='BER'
UNION SELECT 'sas' as company,code,airportname,latitude,longitude FROM sasroute WHERE code='BER'
This gives you between zero and three rows, depending on what tables contain the code 'BER'. An additional column, 'company' tels you which table contains each row.
If I have a SQL table with columns:
NR_A, NR_B, NR_C, NR_D, R_A, R_B, R_C
and on runtime, I add columns following the column's sequence such that the next column above would be R_D followed by R_E.
My problem is I need to reset the values of columns that starts with R_ (labeled that way to indicate that it is resettable) back to 0 each time I re-run my script . NR_ columns btw are fixed, so it is simpler to just say something like:
UPDATE table set col = 0 where column name starts with 'NR_'
I know that is not a valid SQL but I think its the best way to state my problem.
Any thoughts?
EDIT: btw, I use postgres (if that would help) and java.
SQL doesn't support dynamically named columns or tables--your options are:
statically define column references
use dynamic SQL to generate & execute the query/queries
Java PreparedStatements do not insulate you from this--they have the same issue, just in Java.
Are you sure you have to add columns during normal operations? Dynamic datamodels are most of the time a realy bad idea. You will see locking and performance problems.
If you need a dynamic datamodel, take a look at key-value storage. PostgreSQL also has the extension hstore, check the contrib.
If you don't have many columns and you don't expect the schema to change, just list them explicitly.
UPDATE table SET NR_A=0;
UPDATE table SET NR_B=0;
UPDATE table SET NR_C=0;
UPDATE table SET NR_D=0;
Otherwise, a simple php script could dynamically build and execute your query:
<?php
$db = pg_connect("host=localhost port=5432 user=postgres password=mypass dbname=mydb");
if(!$db) die("Failed to connect");
$reset_cols = ["A","B","C","D"];
foreach ($col in $reset_cols) {
$sql = "UPDATE my_table SET NR_" . $col . "=0";
pg_query($db,$sql);
}
?>
You could also lookup table's columns in Postgresql by querying the information schema columns tables, but you'll likely need to write a plpgsql function to loop over the query results (one row per table column starting with "NR_").
if you rather using sql query script, you should try to get the all column based on given tablename.
maybe you could try this query to get all column based on given tablename to use in your query.
SELECT attname FROM
pg_attribute, pg_type
WHERE typname = 'tablename' --your table name
AND attrelid = typrelid
AND attname NOT IN ('cmin', 'cmax', 'ctid', 'oid', 'tableoid', 'xmin', 'xmax')
--note that this attname is sys column
the query would return all column with given tablename except system column