MySQL procedure - how to improve performance of query? - mysql

I have MySQL procedure which is collecting data from 3 tables:
dossier
courrier
courrier_concerne_dossier
Simply I just can't use select * from... I need every dossier_str separated (one dossier_str in each column and all in one big result set).
(SELECT dossier_oid from data.courrier_concerne_dossier where courrier_oid = param_oid LIMIT 1) as 'dossier1_oid',
(SELECT concat(a.prefixe_numero, "-", cast(a.numero as char), " - ",DATE_FORMAT(a.date_ouverture, '%e/%c/%Y'), " - ", b.nom, " - ", a.intitule)
FROM data.dossier as a
JOIN data.client as b on
a.client_oid=b.oid
WHERE a.oid = dossier1_oid) as 'dossier1_str',
(SELECT dossier_oid from data.courrier_concerne_dossier where courrier_oid = param_oid LIMIT 1,1) as 'dossier2_oid',
(SELECT concat(a.prefixe_numero, "-", cast(a.numero as char), " - ",DATE_FORMAT(a.date_ouverture, '%e/%c/%Y'), " - ", b.nom, " - ", a.intitule)
FROM data.dossier as a
JOIN data.client as b on
a.client_oid=b.oid
WHERE a.oid = dossier2_oid) as 'dossier2_str',
(SELECT dossier_oid from data.courrier_concerne_dossier where courrier_oid = param_oid LIMIT 2,1) as 'dossier3_oid',
(SELECT concat(a.prefixe_numero, "-", cast(a.numero as char), " - ",DATE_FORMAT(a.date_ouverture, '%e/%c/%Y'), " - ", b.nom, " - ", a.intitule)
FROM data.dossier as a
JOIN data.client as b on
a.client_oid=b.oid
WHERE a.oid = dossier3_oid) as 'dossier3_str',

Related

How to convert sql to hql with join and max

I am trying to make this query in hql so i don't have to mapper the query result into my java object , but after trying different options, i still can't make it work. Is it possible to perform this query in hql in any way? The query is:
select t.*
from part_movement t
join
( select id_block_movement, max(start_date) as somedate
from part_movement
where id_area_final_destination = 1
and ((id_area_destination != id_area_final_destination and id_user_receiver is not null) or
(id_area_destination = id_area_final_destination and id_user_receiver is null))
group by id_block_movement
) s
on s.id_block_movement = t.id_block_movement
and s.somedate= t.start_date;
ok i got it finally!! It was: (feels wired answearing myself without having any answear from someone else )
Query q2 = s.createQuery(" from PartMovement t "
+ " WHERE t.areaByIdAreaFinalDestination = ? "
+ " AND t.startDate IN (select max(b.startDate) from PartMovement b "
+ " WHERE ((b.areaByIdAreaDestination != b.areaByIdAreaFinalDestination and b.usersByIdUserReceiver is not null) OR "
+ " (b.areaByIdAreaDestination = b.areaByIdAreaFinalDestination and b.usersByIdUserReceiver is null)) "
+ " group by b.idBlockMovement )");

LIMIT CLAUSE With union

I have this kind of query. I am using limit, but this query gives me 20 results. Can anybody tell me why
SELECT
*,
`tablename`.`bookmark_id` as `bookmark_id`,
`tablename`.`bookmark_date` as `bookmark_date`
FROM ( (" + sql1 + ")
UNION ALL (" + sql2 + ")
UNION ALL (" + sql3 + ") ) AS tablename
WHERE `bookmark_id`
NOT IN
(SELECT `table1`.`bookmark_id`
FROM (
(SELECT `user_bookmarks`.`bookmark_id`
FROM `user_bookmarks`
WHERE `user_bookmarks`.`bookmark_id` = `bookmark_id`
AND `user_id` = 26)
UNION
(SELECT `bookmark_id`
FROM `user_deleted_bookmarks`
WHERE `user_id` = ?)
) AS `table1`)
GROUP BY bookmark_id
ORDER BY `bookmark_date`
DESC limit 17, 20
Thanks
From the SELECT docs
With one argument, the value specifies the number of rows to return from the beginning of the result set:
SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows
With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
I think you want LIMIT 16, 4
When you use limit, second argument is number of results to return.
See : http://dev.mysql.com/doc/refman/5.0/en/select.html
In your case you want :
SELECT .... LIMIT 16,4
You will get 4 rows : 17, 18, 19 and 20.
SELECT *,`tablename`.`bookmark_id` as `bookmark_id`,`tablename`.`bookmark_date` as `bookmark_date` FROM ( (" + sql1 + ") union all (" + sql2 + ") union all (" + sql3 + ") ) AS tablename WHERE `bookmark_id` NOT IN (SELECT `table1`.`bookmark_id` FROM ((SELECT `user_bookmarks`.`bookmark_id` FROM `user_bookmarks` WHERE `user_bookmarks`.`bookmark_id` = `bookmark_id` AND `user_id` = 26) UNION (SELECT `bookmark_id` FROM `user_deleted_bookmarks` WHERE `user_id` = ?)) AS `table1`) GROUP BY bookmark_id ORDER BY `bookmark_date`
DESC limit 16, 4;
for getting result 17,18,19,20
it's count start from 17th position and give next 4 values

MySQL permutation

I have two tables. One has products and the other has bundles that go with it. I need to figure out the SQL that allows me to find all the combinations in which I can sell the product with extras.
Products
Name ID
Bench 1
Extra
Name ID Parent ID QTY
undershelf 1 1 1
overshelf 2 1 1
wheels 3 1 1
I need and output table that shows all the combination in which I can sell the product:
Bench
Bench + undershelf
Bench + undershelf + overshelf
Bench + overshelf
Bench + wheels
bench + wheels + overshelf and so one.
Every extras can be in the bundle or not, making that a binary property.
A way to visualize the combination is to create a word with a bit for every extra, 1 mean that the extra is in the list, 0 mean the that it is not.
For example Bench + undershelf + overshelf is 110 (or 011 if the binary string is read in the opposite order)
Generating every combination of n bit will give every combination of n extras, it will also give every number from 0 to 2^n - 1.
We can work back from here:
1. generate the list of number from 0 to 2^n - 1;
2. convert the number to binary, to list the combination of extras
3. match every bit with an extra
4. concatenate the names of the extras in the bundle description.
SELECT CONCAT(b.Name
, COALESCE(CONCAT(' + '
, GROUP_CONCAT(x.Name SEPARATOR ' + '))
, '')) Combination
FROM (SELECT p.Name, p.id
, LPAD(BIN(u.N + t.N * 10), e.Dim, '0') bitmap
FROM Products p
CROSS JOIN (SELECT 0 N UNION ALL SELECT 1
UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9) u
CROSS JOIN (SELECT 0 N UNION ALL SELECT 1
UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9) t
INNER JOIN (SELECT COUNT(1) Dim
, `Parent ID` pID
FROM Extra) E ON e.pID = p.ID
WHERE u.N + t.N * 10 < Pow(2, e.Dim)
) B
LEFT JOIN (SELECT #rownum := #rownum + 1 ID
, `Parent ID` pID
, Name
FROM Extra
, (Select #rownum := 0) r) X
ON x.pID = b.ID
AND SUBSTRING(b.bitmap, x.ID, 1) = '1'
GROUP BY b.Name, b.bitmap
this query will work up to six extras, then it'll need another digit table (one digit every three extras).
How it Works
The subquery E count the number of the extras, this is used in C to limit the elements generated by the digit tables u and t (unit and tens) to 2^dim.
The number is converted to binary by BIN(u.N + t.N * 10), then left padded with '0' to the number of elements, generating a combination bitmap.
To use the generated bitmap each extras need a fake id that will match a position in it, that's what the subquery X is meant for.
The two subqueries are JOINed by the nth char of the bitmap: if the char is 1 the extra is in the bundle, LEFT joined to not loose the product without extras.
I cannot think of any ingenious way of doing this in mysql, but it is very easy in a scripting language. Here in PHP:
<?php
$extra = array('undershelf', 'overshelf', 'sheels');
$possible_combinations = pow(2, count($extra));
for ($i = 0; $i < $possible_combinations; $i++) {
$combo = array('Bench');
foreach ($extra as $j => $item) {
if ($i & pow(2, $j)) {
$combo[] = $item;
}
}
echo implode(' + ', $combo) . "\n";
}
prints
Bench
Bench + undershelf
Bench + overshelf
Bench + undershelf + overshelf
Bench + sheels
Bench + undershelf + sheels
Bench + overshelf + sheels
Bench + undershelf + overshelf + sheels
Possible entirely within MySQL, though not simple. This example can handle up to 5 "extras", and is easily extensible for more:
CREATE TABLE products (name varchar(100), id int primary key);
INSERT INTO products (name, id) VALUES ('Bench', 1);
CREATE TABLE extra (name varchar(100), id int primary key, parent_id int references products.id, qty int);
INSERT INTO extra (name, id, parent_id, qty) VALUES
('undershelf', 1, 1, 1), ('overshelf', 2, 1, 1), ('wheels', 3, 1, 1);
CREATE TABLE boolean_values (x boolean);
INSERT INTO boolean_values VALUES (TRUE), (FALSE);
CREATE VIEW product_extras_interim_vw AS
SELECT p.id product_id, p.name product_name, e.id extra_id, e.name extra_name, x
FROM products p
JOIN extra e ON (e.parent_id = p.id)
CROSS JOIN boolean_values;
SELECT DISTINCT a.product_name
, CASE WHEN a.x THEN CONCAT(' + ', a.extra_name) END extra1
, CASE WHEN b.x THEN CONCAT(' + ', b.extra_name) END extra2
, CASE WHEN c.x THEN CONCAT(' + ', c.extra_name) END extra3
, CASE WHEN d.x THEN CONCAT(' + ', d.extra_name) END extra4
, CASE WHEN e.x THEN CONCAT(' + ', e.extra_name) END extra5
FROM product_extras_interim_vw a
LEFT JOIN product_extras_interim_vw b
ON ( a.product_id = b.product_id
AND b.extra_id > a.extra_id
AND a.x )
LEFT JOIN product_extras_interim_vw c
ON ( a.product_id = c.product_id
AND c.extra_id > b.extra_id
AND b.x )
LEFT JOIN product_extras_interim_vw d
ON ( a.product_id = d.product_id
AND d.extra_id > c.extra_id
AND c.x)
LEFT JOIN product_extras_interim_vw e
ON ( a.product_id = e.product_id
AND e.extra_id > d.extra_id
AND d.x)
ORDER BY product_name, extra1, extra2, extra3, extra4, extra5;
Output:
Bench
Bench + overshelf
Bench + overshelf + wheels
Bench + undershelf
Bench + undershelf + overshelf
Bench + undershelf + overshelf + wheels
Bench + undershelf + wheels
Bench + wheels

Order By with Union Sql Server 2008

CREATE PROCEDURE [dbo].[spReport]
#FromDate DATETIME = NULL,
#ToDate DATETIME = NULL,
#TenantID int ,
#BusinessUnitId int
AS
BEGIN
Declare #listStr Varchar(max), #listValue Varchar(max)
Select
#listStr = COALESCE(#listStr+',' ,'') + FieldLabel
From
(Select Distinct Top 100
FieldLabel, ControlTypeId
From
PaymentCustomFieldDefinitions PCFD
Inner Join
Product P On P.Id = PCFD.ProductId
Where
P.TenantId = #TenantId
Order By
ControlTypeId Desc) R
Set #listStr = ',' + #listStr
Set #listStr = IsNull(#listStr, '')
Select
'Confirmation Number,Business Unit,Bank Account,Merchant Account,Product Name,Payment Date,Payment Time,Total Amount,Status,First Name,Last Name,Payment Method' + #listStr
Union
SELECT
p.ConfirmationNumber + ',' + bu.Name + ',' + p.TenantBankAccountName + ',' + Case When ma.Name IS NULL then '' ELSE ma.Name END + ',' + pd.Name + ',' +
cast(P.PaymentDate as Varchar(11)) + ',' + convert(VARCHAR(8), P.PaymentDate,108) + ',' + Cast(p.TotalDue As Varchar(20)) + ',' + p.PaymentStatusText + ',' + p.PayorFirstName + ',' + p.PayorLastName + ',' + p.PaymentMethodText + ',' + [dbo].[GetPaymentReferenceAndCustomFields](p.Id,#listStr)
FROM
Payment p
INNER JOIN
Product pd ON p.ProductId = pd.Id
INNER JOIN
BusinessUnit bu ON pd.BusinessUnitId = bu.Id
INNER JOIN
ProductDetailPayment pdp ON p.ProductId = pdp.ProductId
LEFT OUTER JOIN
MerchantAccount ma ON ma.Id = pdp.MerchantAccountId
WHERE
p.PaymentDate BETWEEN #FromDate AND #ToDate
AND p.TenantId = #TenantId AND pd.BusinessUnitId= #BusinessUnitId
ORDER BY
p.ProductId desc
END
Getting this error when using Order by :
Msg 4104, Level 16, State 1, Procedure spReport, Line 41
The multi-part identifier "p.ProductId" could not be bound.
Msg 104, Level 16, State 1, Procedure spQueryPaymentDetailReport, Line 41
ORDER BY items must appear in the select list if the statement contains a UNION, INTERSECT or EXCEPT operator.
You can't reference p.ProductId in the ORDER BY because the first subquery doesn't have a p dataset.
You can't reference a ProductId column in the ORDER BY because there's no column by that name in the combined result set.
To solve these issues, you could add a ProductId column and, if the final output must contain a single column like in your query, use a derived table:
SELECT
p.CSV
FROM (
Select
ProductId = 2147483647,
CSV = 'Confirmation Number,Business Unit,Bank Account,Merchant Account,Product Name,Payment Date,Payment Time,Total Amount,Status,First Name,Last Name,Payment Method' + #listStr
Union
SELECT
p.ProductId,
p.ConfirmationNumber + ',' + bu.Name + ',' + p.TenantBankAccountName + ',' + Case When ma.Name IS NULL then '' ELSE ma.Name END + ',' + pd.Name + ',' +
cast(P.PaymentDate as Varchar(11)) + ',' + convert(VARCHAR(8), P.PaymentDate,108) + ',' + Cast(p.TotalDue As Varchar(20)) + ',' + p.PaymentStatusText + ',' + p.PayorFirstName + ',' + p.PayorLastName + ',' + p.PaymentMethodText + ',' + [dbo].[GetPaymentReferenceAndCustomFields](p.Id,#listStr)
FROM
Payment p
INNER JOIN
Product pd ON p.ProductId = pd.Id
INNER JOIN
BusinessUnit bu ON pd.BusinessUnitId = bu.Id
INNER JOIN
ProductDetailPayment pdp ON p.ProductId = pdp.ProductId
LEFT OUTER JOIN
MerchantAccount ma ON ma.Id = pdp.MerchantAccountId
WHERE
p.PaymentDate BETWEEN #FromDate AND #ToDate
AND p.TenantId = #TenantId AND pd.BusinessUnitId= #BusinessUnitId
) p
ORDER BY
p.ProductId desc
;
The first row is assigned the MaxInt ID value because, as I understand, it is the header row and must go first according to the specified ORDER BY p.ProductId DESC clause (and because I've assumed the ProductId is an int, of course).

how to use limit keyword in oracle

I am retrieving data from table but instead of all row, I want 20 rows at a time for pagination. For this I use limit keyword which work perfectly in Mysql but not in Oracle.
Code:
"select "+ "C.CONTRACTOR_ID,C.CONTRACTOR_NAME,nvl(C.CONTACT_PERSON_1,'-'),nvl(C.CONTACT_PERSON_2,'-'),C.REGISTRATION_NO,CRA.DESCRIPTION REG_AUTH_NAME,"+
"to_char(C.VALID_FROM,'dd/mm/yyyy'),to_char(C.VALID_TO,'dd/mm/yyyy'),CC.DESCRIPTION CONTRACTOR_CLASS,C.INCORP_PLACE,"+
"IT.DESCRIPTION INCORP_TYPE,nvl(to_char(C.DATE_OF_INCORP,'dd/mm/yyyy'),'-') DATE_OF_INCORP,C.ADDRESS1,nvl(C.ADDRESS2,'-'),nvl(C.EMAIL_ID,'-'),"+
"nvl(C.WEBSITE_URL,'-'),nvl(C.PHONE_NO,'-'),nvl(C.FAX_NO,'-'),nvl(C.MOBILE_NO,'-'),C.BANK_NAME,C.BANK_BRANCH,C.ACCOUNT_NO,C.IFSC_CODE," +
"C.PAN_NO,nvl(C.TIN_NO,'-'),nvl(C.CST_NO,'-') "+
"from "+
"CONTRACTOR C "+
"inner join CONTRACTOR_REG_AUTH CRA on CRA.REG_AUTH_ID=C.REG_AUTH_ID "+
"inner join CONTRACTOR_CLASS CC on CC.CLASS_ID=C.CONTRACTOR_CLASS_ID "+
"inner join INCORPORATION_TYPE IT on IT.INCORP_TYPE=C.INCORP_TYPE "+
"limit " + offset + ", " + noOfRecords ";
Here no order by keyword is there. I am retrieving data from different table and then display only 20 rows at a time.
In Oracle, you can use the special rownum variable. This example behaves like limit FirstRow, NrOfRows:
select *
from (
select *
, rownum as rn
from YourTable
order by
id
) as SubQueryAlias
where FirstRow <= rn
and rn < FirstRow + NrOfRows
An optimized version of this query from AskTom, linked from this SO question:
select *
from (
select /*+ FIRST_ROWS(n) */
rownum as rn
, *
from (
select *
from YourTable
order by
id
) as SubQueryAlias1
where rownum <= FirstRow + NrOfRows
) as SubQueryAlias2
where rn >= FirstRow