regularexpression for this text sql statement or a program? - sql

Heres specifically the sql text in a file.
select substr(to_char(ctl.tody_run_dt,'YYYYMMDD'),1,8) tody_yyyymmdd,
substr(to_char(cdr.nxt_proc_dt,'YYYYMMDD'),1,8) nxt_proc_yyyymmdd,
add_months(ctl.tody_run_dt - cdr.past_accru_dys,
- ct.nbr_cycl_for_adj) beg_proc_dt,
from tbl_crd )
and prv.calendar_run_dt =
( select max(calendar_run_dt)
from run_tbl1 prv2
From this i wish to extract all the tables,
This seems pretty complicated to be done through a regexp? Is there a way? Or should i write a program? I just cant come up with an algorithm.

You might be able to do something like a linear search like this. It relaxed for your example
and just targets the from keyword, excludes other keywords.
The table data is captured in group 1. It has to be split appart upon each
match through the find loop.
# from\s+((?!(?:select|from|where|and)\b)\w+(?:[,\s]+(?!(?:select|from|where|and)\b)\w+)*)
from
\s+
( # (1 start), Contains all the table info
(?! # exclude keywords
(?:
select
| from
| where
| and
)
\b
)
\w+
(?:
[,\s]+
(?! # exclude keywords
(?:
select
| from
| where
| and
)
\b
)
\w+
)*
) # (1 end)
Perl test case
$/ = undef;
$str = <DATA>;
while ( $str =~ /from\s+((?!(?:select|from|where|and)\b)\w+(?:[,\s]+(?!(?:select|from|where|and)\b)\w+)*)/g )
{
print "\n'$1'";
}
__DATA__
select substr(to_char(ctl.tody_run_dt,'YYYYMMDD'),1,8) tody_yyyymmdd,
substr(to_char(cdr.nxt_proc_dt,'YYYYMMDD'),1,8) nxt_proc_yyyymmdd,
add_months(ctl.tody_run_dt - cdr.past_accru_dys,
- ct.nbr_cycl_for_adj) beg_proc_dt,
(ctl.tody_run_dt + cdr.futr_accru_dys) end_proc_dt,
ctl.tody_end_proc_dt,
ctl.prv_end_proc_dt,
cdr.fst_proc_dy,
cdr.lst_proc_dy,
cdr.accru_nbr_of_dys,
cdr.dy_of_wk,
from run_tbl1 cdr, runtbl
run_tbl1 prv,
run_tbl_cntl ctl,
tbl_crd ct
where cdr.calendar_run_dt = ctl.tody_run_dt
and ct.nbr_cycl_for_adj =
( select max(nbr_cycl_for_adj)
from tbl_crd )
and prv.calendar_run_dt =
( select max(calendar_run_dt)
from run_tbl1 prv2
where prv2.calendar_run_dt < ctl.tody_run_dt
and prv2.accru_nbr_of_dys = 1 )
and rownum = 1
Output >>
'run_tbl1 cdr, runtbl
run_tbl1 prv,
run_tbl_cntl ctl,
tbl_crd ct'
'tbl_crd'
'run_tbl1 prv2'

First I had to correct some syntax errors within your SQL.
... cdr.dy_of_wk, <<<< the comma is wrong
from run_tbl1 cdr ...
Here the proove of concept using JSQLParser V0.8.9 (https://github.com/JSQLParser/JSqlParser) to extract tablenames.
public static void main(String[] args) throws JSQLParserException {
TablesNamesFinder tfinder = new TablesNamesFinder();
String sql = "select substr(to_char(ctl.tody_run_dt,'YYYYMMDD'),1,8) tody_yyyymmdd, "
+ " substr(to_char(cdr.nxt_proc_dt,'YYYYMMDD'),1,8) nxt_proc_yyyymmdd, "
+ " add_months(ctl.tody_run_dt - cdr.past_accru_dys, "
+ " - ct.nbr_cycl_for_adj) beg_proc_dt, "
+ " (ctl.tody_run_dt + cdr.futr_accru_dys) end_proc_dt, "
+ " ctl.tody_end_proc_dt, "
+ " ctl.prv_end_proc_dt, "
+ " cdr.fst_proc_dy, "
+ " cdr.lst_proc_dy, "
+ " cdr.accru_nbr_of_dys, "
+ " cdr.dy_of_wk "
+ " from run_tbl1 cdr, runtbl, "
+ " run_tbl1 prv, "
+ " run_tbl_cntl ctl, "
+ " tbl_crd ct "
+ " where cdr.calendar_run_dt = ctl.tody_run_dt "
+ " and ct.nbr_cycl_for_adj = "
+ " ( select max(nbr_cycl_for_adj) "
+ " from tbl_crd ) "
+ " and prv.calendar_run_dt = "
+ " ( select max(calendar_run_dt) "
+ " from run_tbl1 prv2 "
+ " where prv2.calendar_run_dt < ctl.tody_run_dt "
+ " and prv2.accru_nbr_of_dys = 1 ) "
+ " and rownum = 1 ";
//parse SQL statement
Select select = (Select) CCJSqlParserUtil.parse(sql);
//extract table names
List<String> tableList = tfinder.getTableList(select);
System.out.println(tableList);
}
and it outputs
[run_tbl1, runtbl, run_tbl_cntl, tbl_crd]

Related

SQL query to select group then order from 2 tables

Here are the tables
TAGS :
tag_id
tag_name
1
SENT
2
AIRTIME
3
RECEIVED
4
KOPOKOPO
5
RESTAURANT
6
PAID
7
UBER
TRANS_TAG
tag_id
trans_id
1
1
2
1
3
1
4
1
5
1
6
1
1
2
2
2
3
2
4
2
5
2
6
2
The following are default tags (SENT, AIRTIME, RECEIVED, PAID), the rest are not default tags.
The TRANS_TAG table tracks a transaction id and the tags attached to it.
I would like to write a select SQL statement that selects from these two tables and achieves the following result. - it returns a list of all the tags that have been attached to at least one transaction. it then orders them alphabetically but grouped with the default tags first.
This is the desired result
tag_name
AIRTIME
PAID
RECIVED
SENT
KOPOKOPO
RESTAURANT
This is the code that I have so far
String SQL = "SELECT "
+ KEY_TAG_TITLE +
" FROM " + TABLE_TRANS_TAG
+ " INNER JOIN " + TABLE_TAG + " " + "ON " + TABLE_TRANS_TAG + "." + KEY_TRANS_TAG_TAG_ID
+ " = " + TABLE_TAG + "." + KEY_TAG_ID
+ " GROUP BY " + KEY_TAG_TITLE
+ " ORDER BY " + TABLE_TAG + "." + KEY_TAG_TITLE + " ASC, " + TABLE_TAG + "." + KEY_ROW_ID + " ASC";
You can use:
SELECT T.KEY_TAG_TITLE
FROM TABLE_TRANS_TAG TT INNER JOIN
TABLE_TAG T
ON TT.KEY_TRANS_TAG_TAG_ID = T.KEY_TAG_ID
GROUP BY T.KEY_TAG_TITLE
ORDER BY (CASE WHEN T.KEY_TAG_TITLE IN ('SENT', 'AIRTIME', 'RECEIVED', 'PAID') THEN 1 ELSE 2 END),
T.KEY_TAG_TITLE;
Don't use join and aggregation for such a simple requirement.
It would result in poor performance.
Use EXISTS and conditional sorting:
String SQL = "SELECT tg." + KEY_TAG_TITLE + " " +
"FROM " + TABLE_TAG + " AS tg " +
"WHERE EXISTS (SELECT 1 FROM " + TABLE_TRANS_TAG + " AS tr WHERE tr." + KEY_TRANS_TAG_TAG_ID + " = tg." + KEY_TAG_ID + ") " +
"ORDER BY tg." + KEY_TAG_TITLE + " IN ('SENT', 'AIRTIME', 'RECEIVED', 'PAID') DESC, tg." + KEY_TAG_TITLE;

"ORA-00920: invalid relational operator" Error

select
ic.item_name,
lh.locn_brcd from_locn,
lh2.locn_brcd to_locn,
wl.from_container,
wl.to_container,
wl.units,
wl.prev_from_container_status prev_from_lpn_status,
wl.curr_from_container_status curr_from_lpn_status,
wl.prev_to_container_status prev_to_lpn_status,
wl.curr_to_container_status curr_to_lpn_status,
wl.work_batch_number,
wl.transaction_name,
wl.action,
wl.work_id,
wl.date_updated,
wl.source_updated,
wl.tote_number,
wl.chute
from m_work_log wl
LEFT join item_cbo ic on wl.item_id=ic.item_id
left join locn_hdr lh on wl.from_location_id = lh.locn_id
left join locn_hdr lh2 on wl.to_location_id = lh2.locn_id
where wl.action in (:action)
and trunc(wl.date_updated) between :start_date and :end_date
and (ic.item_name in (:list) OR
wl.source_updated = :username OR
wl.to_container in (:LPNList) OR
(:list is null and :username is null and :LPNList is null)
)
order by date_updated desc
Hi everyone,
when I run this code through Oracle SQL Developer and I add two items to the :list parameter and two items to the :action parameter it works fine. But when I run this through SSRS (report builder ) it fails to run and I get an "ORA-00920: invalid relational operator". I'm new to SQL and i'm not sure what I am doing incorrectly here. Any help is greatly appreciated. Thanks!
There are 2 ways to do this:
Multiple Value Parameter:
First of all, you must use Oracle provider, multiple value paramaters does not work with neither ODBC nor OLEDB connections (reference).
Here is an external link explaining in detail here.
Using an expression as the query by putting the whole thing like this ="query_here"
="select "
+ " ic.item_name,"
+ " lh.locn_brcd from_locn,"
+ " lh2.locn_brcd to_locn,"
+ " wl.from_container,"
+ " wl.to_container,"
+ " wl.units,"
+ " wl.prev_from_container_status prev_from_lpn_status,"
+ " wl.curr_from_container_status curr_from_lpn_status,"
+ " wl.prev_to_container_status prev_to_lpn_status,"
+ " wl.curr_to_container_status curr_to_lpn_status,"
+ " wl.work_batch_number,"
+ " wl.transaction_name,"
+ " wl.action,"
+ " wl.work_id,"
+ " wl.date_updated,"
+ " wl.source_updated,"
+ " wl.tote_number,"
+ " wl.chute"
+ "from m_work_log wl"
+ " LEFT join item_cbo ic on wl.item_id=ic.item_id"
+ " left join locn_hdr lh on wl.from_location_id = lh.locn_id"
+ " left join locn_hdr lh2 on wl.to_location_id = lh2.locn_id"
+ "where wl.action in (:action)"
+ " and trunc(wl.date_updated) between :start_date and :end_date"
+ " and (ic.item_name in ('" + Join(Parameters!list.Value , "', '")" + ') OR"
+ " wl.source_updated = :username OR"
+ " wl.to_container in ('" + Join(Parameters!LPNList.Value , "', '")" + ') OR"
+ " (:list = '_N/A_' and :username is null and :LPNList = '_N/A_')"
+ " )"
+ " order by date_updated desc"
In this case you will need to provide default empty values to your lists. I used 'N/A' in my example.

Multiples statements where clause with differents values in Sql using JPA

Hi guys I´m doing a native query for my project using JPA, but i don´t know how can I do a type of if and else
in a where clause, my ?0 can be 4 values: 10,20,30 and 40, when ?0 is 10, 20, 30 I should use CI.QTD <=
and when ?0 is 40, the condition should be >= . How can I do this?
Follow my code with one condition:
SELECT rownum AS id,
x.*
FROM (
SELECT ci.text,
ci.lenght
FROM ci_table CI
WHERE (?0 IS NULL OR ci.qtd <= ?0)
GROUP BY ci.text,
ci.lenght
ORDER BY ci.text) x ,
nativequery = true);
ADD THE QUERY AFTER THE ADJUSTMENT:
#Query(value =
"SELECT rownum as ID, X.* FROM (SELECT " +
" CI.PARAM1 " +
" CI.PARAM2, " +
" CI.PARAM3, " +
" CI.PARAM4, " +
" CI.PARAM5" +
" FROM " +
" CM_PARAMS CI " +
" WHERE " +
" (?1 is null or CI.PARAM6 = ?1) " +
" AND (?2 is null or CI.PARAM7 = ?2) " +
" AND (?3 is null or CI.PARAM8 = ?3) " +
" AND (?4 is null or CI.PARAM9 = ?4) " +
" AND (?5 is null or CI.PARAM10 = ?5) " +
" AND (?6 is null or CI.PARAM11 = ?6) " +
" AND (?7 is null or CI.PARAM12 = ?7) " +
" AND (?8 is null or CI.PARAM13 = ?8) " +
" AND (CASE WHEN ?9 >30 THEN CI.PARAM14 > 30 " +
" CASE WHEN ?9 <31 THEN CI.PARAM15 <= ?9 END) = 1 " +
" GROUP BY " +
" CI.PARAM1, " +
" CI.PARAM2, " +
" CI.PARAM3, " +
" CI.PARAM4, " +
" CI.PARAM5" +
" ORDER BY " +
" CI.PARAM1 ASC) X " , nativeQuery = true)
Try:
SELECT rownum AS id,
x.*
FROM (
SELECT ci.text,
ci.lenght
FROM ci_table CI
WHERE (CASE WHEN ?0 IN (10,20,30) THEN CI.QTD <= ?0
WHEN ?0 = 40 THEN CI.QTD > ?0 END) = 1
GROUP BY ci.text,
ci.lenght
ORDER BY ci.text) x ,
nativequery = true);

SQL Join Query taking long to complete

I am working on a project that require me to join four tables. I have written this code but it's taking forever to finish. Please help. Ohhh I have about 121 000 entries in the Db
PortfolioCollectionDataContext context = null;
context = DataContext;
var Logins = from bkg in context.EnquiryBookings
where bkg.Paid == true
from log in context.Logins
where log.LoginID == bkg.LoginID
from enq in context.Enquiries
where enq.EnquiryID == bkg.EnquiryID
from estb in context.Establishments
where enq.EstablishmentID == estb.EstablishmentID
select new
{
log.LoginID,
log.FirstName,
log.LastName,
log.CountryOfResidence,
log.EmailAddress,
log.TelephoneNumber,
bkg.TotalPrice,
estb.CompanyName
};
string str = "";
foreach (var user in Logins)
{
str += ("[Name: " + user.LastName + " " + user.FirstName + " - Country: " + user.CountryOfResidence + " - Phone: " + user.TelephoneNumber + " - Email: " + user.EmailAddress + " - Booked From: " + user.CompanyName + " - Spent: " + user.TotalPrice.ToString() + "]");
}
return str;
Use following query on LINQ
PortfolioCollectionDataContext context = null;
context = DataContext;
var Logins = from bkg in context.EnquiryBookings
join log in context.Logins
on log.LoginID equals bkg.LoginID
&& bkg.Paid == true
join enq in context.Enquiries
on enq.EnquiryID equals bkg.EnquiryID
join estb in context.Establishments
on enq.EstablishmentID == estb.EstablishmentID
select new
{
str = "[Name: " + log.LastName + " " + log.FirstName + " - Country: " + log.CountryOfResidence + " - Phone: "
+ log.TelephoneNumber + " - Email: " + log.EmailAddress + " - Booked From: "
+ estb.CompanyName + " - Spent: " + bkg.TotalPrice.ToString() + "]"
};
string output = string.Join(", ", Logins.ToList());
return output;
Check your query by taking cursor on Logins and paste that query here. Then check an estimated execution plan of your query and paste here.
If using SQL Server, to get execution plan of your query using Sql server management studio, click on an icon highlighted in an image below.

SQL Server 2008 R2 Express multi-part could not be bound

I know similar questions has been before but I just couldn't quite understand them, still very new to SQL and wanting to get the solution as well as understanding why it wouldn't work originally.
sql = "UPDATE e " +
"SET " +
"e.Operator = '" + emp.Operator + "', " +
"e.LoginName = '" + emp.Login + "', " +
"e.Active = " + (emp.Active == true ? 1 : 0) + "," +
"e.Position = '" + emp.Position + "', " +
"p.Admin = " + (emp.Permission.Admin == true ? 1 : 0) + "," +
"p.Manager = " + (emp.Permission.Manager == true ? 1 : 0) + "," +
"p.Overtime = " + (emp.Permission.Overtime == true ? 1 : 0) + "," +
"p.TimeInLieu = " + emp.Permission.TimeInLieu + " " +
"FROM Employee e INNER JOIN Permissions p " +
"ON e.PermissionID = p.PermissionID AND e.Operator = '" + employee + "'";
when trying to execute the command I get this error.
The multi-part identifier "p.Admin" could not be bound.
Any help would be greatly received.