Optimization SQL, not in/not exists? - sql

I have a request, please tell me how you can optimize it?
select distinct
trunc(dw.mdf_date) as mdf_date
,dw.dss_id
,dw.raid
,dw.host_type
,dw.volume_name
,dw.volume_size
,dw.prv
,listagg(dw.hba_wwn,',' on overflow truncate '...' without count) within group (order by dw.hba_wwn) as wwn
from
dss_wwn dw
where
dw.volume_name not in ('ADMIN')
and dw.volume_name not like '.%'
and dw.hba_wwn is not null
and not exists (select 1 from wwn shw where shw.wwn = dw.hba_wwn and shw.dic_type_eqp_id = 4 and rownum = 1)
and not exists (select 1 from dss_vmhdd shw where shw.wwid = dw.disk_wwn and rownum = 1)
group by
trunc(dw.mdf_date)
,dw.dss_id
,dw.raid
,dw.host_type
,dw.volume_name
,dw.volume_size
,dw.prv
This request works for 23 seconds.
And if you comment out this line, That works fast 0.2 seconds
and not exists (select 1 from wwn shw where shw.wwn = dw.hba_wwn and shw.dic_type_eqp_id = 4 and rownum = 1)
select count(*) from DSS_WWN --100000
select count(*) from WWN t --13000
UPD #Gro Thanks for your answer, really after I removed rownum=1 request fulfilled in 0.4 seconds

Related

MS SQL seems to cache select result

I am currently creating a selection query and observed a strange behaviour. Perhaps someone can explain this.
Please check out the following query:
SELECT
(SELECT count(*) from [DummyData].[dbo].[Users]) as numberOfEntriesInDummy,
(ABS(checksum(Name) % (SELECT count(*) from [DummyData].[dbo].[Users])) + 1) as randomId,
(Select [Name] FROM [DummyData].[dbo].[Users] WHERE Id = (ABS(checksum(Name) % (SELECT count(*) from [DummyData].[dbo].[Users])) + 1)) as randName
FROM [invoiceR-Test].[dbo].[AbpUsers]
This query gives me this result:
numberOfEntriesInDummy randomId randName
14 9 Leano
14 9 Leano
14 3 Leano
14 5 Leano
14 13 Leano
14 11 Leano
What I do not understand is why gives the "randName" column always the same result? "Leano" is only once in the [DummyData].[dbo].[Users]-Table and has the ID 7. Actually I would expect that the last column has changing names in it.
The second column shows clearly that the randomId is actually changing form row to row - but the queried result in the last column is always the same. For me it looks like the query result to the [DummyData].[dbo].[Users]-Table is somehow cached...
I think this is an error because you have not qualified your column references. The relevant part of your query is:
SELECT . . .
(SELECT [Name]
FROM [DummyData].[dbo].[Users]
WHERE Id = (ABS(checksum(Name) %
(SELECT count(*) FROM [DummyData].[dbo].[Users])) + 1)) as randName
)
FROM [invoiceR-Test].[dbo].[AbpUsers];
My guess is that you intend:
SELECT . . .
(SELECT u.[Name]
FROM [DummyData].[dbo].[Users] u
WHERE u.Id = (ABS(checksum(u.Name) %
(SELECT count(*) FROM [DummyData].[dbo].[Users])) + 1)) as randName
)
FROM [invoiceR-Test].[dbo].[AbpUsers] au;
However, users doesn't have a name column, so this is interpreted as:
SELECT . . .
(SELECT au.[Name]
FROM [DummyData].[dbo].[Users] u
WHERE u.Id = (ABS(checksum(au.Name) %
(SELECT count(*) FROM [DummyData].[dbo].[Users])) + 1)) as randName
)
FROM [invoiceR-Test].[dbo].[AbpUsers] au;
The moral is to always qualify ALL column references in a query.

Column ambiguously defined error. Working without pagination?

I just want to figure whats wrong with below query :-
If we remove the pagination Rownum part it works fine.
Mentioned is the query below:-
We have tried with removing pagination and it works but we are not able
to make it work with pagination and its giving ambiguity error. I can also see all columns are with their tableNames.
--
SELECT *
FROM
(SELECT a.* ,
ROWNUM rnum
FROM
(WITH TEMP_DCS AS (SELECT ACCOUNT_CYCLE_INV_DATE.ACCT_ID, ACCOUNT_CYCLE_INV_DATE.HIERARCHY_SOURCE,
ACCOUNT_CYCLE_INV_DATE.INV_DATE, ACCOUNT_CYCLE_INV_DATE.INVOICE_NUM, ACCOUNT_CYCLE_INV_DATE.DATA_GROUP, ACCOUNT_CYCLE_INV_DATE.BILL_SYSTEM_ID
FROM
ACCOUNT_CYCLE_INV_DATE_302345 ACCOUNT_CYCLE_INV_DATE
WHERE DATA_GROUP=20180118
AND BILL_SYSTEM_ID = 6)
/* Formatted on 4/25/2018 2:26:23 PM (QP5 v5.115.810.9015) */
SELECT
/*+ leading(TEMP_DCS DIM_HIERARCHY FACT_TAX) full(TEMP_DCS) */
DIM_HIERARCHY.ACCT_LBL,
DIM_HIERARCHY.ACCT_DESC,
DIM_HIERARCHY.ACCT_FMT,
DIM_HIERARCHY.ACCT_ID,
DIM_LOCATION.ADDR1,
DIM_LOCATION.ADDR2,
DIM_LOCATION.ADDR3,
DIM_LOCATION.ADDR4,
DIM_LOCATION.ADDR5,
DIM_HIERARCHY.ADMIN_ID,
DIM_HIERARCHY.AGCY_HIER_CD,
DIM_HIERARCHY.AGCY_HIER_NM,
DIM_HIERARCHY.AGGREGATION_ATTR ,
DIM_HIERARCHY.AGGLVLTYPE,
DIM_HIERARCHY.AGGRFMT AS AGGLVLID,
DIM_HIERARCHY.HPID,
DIM_HIERARCHY.AGGRLBL,
DIM_HIERARCHY.AGGR_CUSTOM_LABEL,
REF_BPI_PROVIDER.AREA_ID,
REF_BPI_PROVIDER.BC_DESC,
DIM_HIERARCHY.WORK_CIRCUIT_ID_1,
REF_BPI_PROVIDER.CB_DESC,
REF_BPI_PROVIDER.CHANGE_BY,
REF_BPI_PROVIDER.CHANGE_DT,
FACT_TAX.CHARGE_GROUP_ID,
REF_BPI_PROVIDER.CIC,
DIM_LOCATION.CITY,
FACT_TAX.CNTNUMBER,
REF_BPI_PROVIDER.COMMENTS,
DIM_HIERARCHY.COMM_SVC_AUTH_NB,
FACT_TAX.SUM_AMOUNT_TAX,
FACT_TAX.TAX_GROUP,
DIM_HIERARCHY.FRGN_ACC_1,
DIM_HIERARCHY.FRGN_ACC_2,
DIM_HIERARCHY.GROUPTYPE,
DIM_HIERARCHY.GROUP_LBL,
DIM_HIERARCHY.GROUP_FMT,
DIM_HIERARCHY.GROUP_DESC,
DIM_HIERARCHY.GROUP_ID,
DIM_LOCATION.HS_LOCATION_ID,
DIM_LOCATION.HS_LOCATION_NAME,
FACT_TAX.INTERNATIONAL_TAX_AMT,
DIM_HIERARCHY.INV_CUST_NUM,
FACT_TAX.INVOICE_NUM,
FACT_TAX.INV_DATE,
DIM_HIERARCHY.IP_SRV_ACC_NO,
FACT_TAX.LOCID,
DIM_HIERARCHY.MRK_AREA,
DIM_LOCATION.MOW_CNTRYID,
FACT_TAX.MOW_TAX_PERCENTAGE,
DIM_HIERARCHY.MSTR_ACCT_NBR,
REF_BPI_PROVIDER.ORIG_COMP_CD,
DIM_HIERARCHY.ORIG_SYSACCT_ID,
DIM_HIERARCHY.ORIG_SYSACCT_CD,
DIM_HIERARCHY.PRODUCT_FAMILY_ID,
REF_PRODUCT_FAMILY.PRODUCT_FAMILY,
REF_PRODUCT_FAMILY.PRODUCT_FAMILY_DESC,
TEMP_DCS.ACCT_ID,
TEMP_DCS.HIERARCHY_SOURCE,
TEMP_DCS.INV_DATE,
TEMP_DCS.INVOICE_NUM,
TEMP_DCS.BILL_SYSTEM_ID,
DIM_SUB_ADDL_INFO.SUB_ACCT_ATTR1,
DIM_HIERARCHY.PON,
DIM_HIERARCHY.PORTID,
DIM_HIERARCHY.PORTID1,
DIM_HIERARCHY.PROVIDER_ID,
REF_BPI_PROVIDER.PSEUDO_CIC,
REF_PROD_TYPE.PRODUCT_TYPE_ID,
REF_PROD_TYPE.PRODUCT_TYPE_DESC AS PTDESC,
DIM_HIERARCHY.PRODUCT_TYPE_ID,
DIM_HIERARCHY.RAO,
DIM_HIERARCHY.REGN_CD,
REF_BPI_PROVIDER.SBC_AFFL_IND,
DIM_HIERARCHY.SBU_DESC,
DIM_HIERARCHY.SBU_FMT,
DIM_HIERARCHY.SBU_LBL,
DIM_LOCATION.SERVICE_CTR,
DIM_HIERARCHY.SERVICE_FMT,
DIM_HIERARCHY.SERVICE_FMT2,
DIM_HIERARCHY.SERVICE_FMT3,
DIM_HIERARCHY.SERVICE_FMT4,
DIM_HIERARCHY.SERVICE_ID,
DIM_HIERARCHY.SERVICE_LBL,
DIM_LOCATION.SITE_ALIAS,
DIM_LOCATION.SITE_ID,
DIM_HIERARCHY.SRC_BILLER,
REF_BPI_PROVIDER.STATUS_CD,
REF_STCNTRY.STCNTRYTXT,
FACT_TAX.STCNTRY_ID,
DIM_HIERARCHY.SUBACCTYPE,
DIM_HIERARCHY.SUB_DEP_ID,
DIM_HIERARCHY.SUB_ACCT_ID,
DIM_HIERARCHY.SVCARRTYPE,
REF_BPI_PROVIDER.SVC_PRVDR_DESC,
REF_TAX.TAX_DESC AS TAXDESC,
FACT_TAX.TAX_SURCG_IND,
FACT_TAX.TAX_TYPE_CD,
DIM_HIERARCHY.LEG_TCCUSTID,
REF_TRANS_CODE.TRANS_CODE_DESC,
DIM_HIERARCHY.LEG_TCINVID,
FACT_TAX.TEL_PROVIDER_CD,
FACT_TAX.TOT_TAX_TRANS,
FACT_TAX.TOT_TAX_WITHLD,
DIM_LOCATION.TO_END_USR_CITY,
DIM_LOCATION.TO_END_USR_CUST_NAME,
DIM_LOCATION.TO_END_USR_STATE,
DIM_LOCATION.TO_END_USR_STREET,
DIM_LOCATION.TO_END_USR_ZIP,
FACT_TAX.TRANSCODE_ID,
FACT_TAX.MOW_TAX_WORDING,
DIM_HIERARCHY.WORK_CIRCUIT_ID_2,
DIM_HIERARCHY.WORK_CIRCUIT_ID_3,
DIM_HIERARCHY.WORK_CIRCUIT_ID_4,
DIM_HIERARCHY.WORK_CIRCUIT_ID_5,
DIM_HIERARCHY.WORK_CIRCUIT_ID_6,
DIM_HIERARCHY.WORK_CIRCUIT_ID_7,
DIM_HIERARCHY.WORK_CIRCUIT_ID_8,
DIM_LOCATION.ZIP_CODE,
DIM_HIERARCHY.BUNDLE_FAN,
REF_CHARGE_GROUP.CHARGE_GROUP_ID,
REF_CHARGE_GROUP.CHARGE_GROUP_DESC,
DIM_HIERARCHY.DEP_ID,
DIM_HIERARCHY.DLCI,
DIM_HIERARCHY.DLCI1,
REF_BPI_PROVIDER.EBAT_DESC,
REF_BPI_PROVIDER.EDI_DESC,
DIM_LOCATION.EOL_NUM,
FACT_TAX.CURRENCY_CD,
FACT_TAX.FFP_TAX_INC_IND,
FACT_TAX.BAND,
REF_PROD_TYPE.PRODUCT_TYPE_CODE,
REF_CHARGE_GROUP.CHARGE_GROUP_CODE,
REF_TRANS_CODE.TRANS_CODE,
DIM_HIERARCHY.BILLER_SERVICE,
DIM_LOCATION.LOCATION_ADDRESS
FROM DIM_HIERARCHY,
REF_BPI_PROVIDER,
FACT_TAX,
DIM_LOCATION,
REF_PRODUCT_FAMILY,
TEMP_DCS,
DIM_SUB_ADDL_INFO,
REF_PROD_TYPE,
REF_STCNTRY,
REF_TAX,
REF_TRANS_CODE,
REF_CHARGE_GROUP
WHERE DIM_HIERARCHY.ACCT_ID = TEMP_DCS.ACCT_ID
AND DIM_HIERARCHY.BILL_SYSTEM_ID = TEMP_DCS.BILL_SYSTEM_ID
AND DIM_HIERARCHY.BILLER_SERVICE = TEMP_DCS.HIERARCHY_SOURCE
AND FACT_TAX.INVOICE_NUM =TEMP_DCS.INVOICE_NUM
AND FACT_TAX.BILL_SYSTEM_ID = TEMP_DCS.BILL_SYSTEM_ID
AND FACT_TAX.INVOICE_NUM = TEMP_DCS.INVOICE_NUM
AND FACT_TAX.INV_DATE = TEMP_DCS.INV_DATE
AND DIM_HIERARCHY.BILL_HIERARCHY_ID = FACT_TAX.BILL_HIERARCHY_ID
AND DIM_HIERARCHY.ACCT_PART_KEY = FACT_TAX.ACCT_PART_KEY
AND DIM_HIERARCHY.BILL_SYSTEM_ID = FACT_TAX.BILL_SYSTEM_ID
AND DIM_HIERARCHY.BILL_SYSTEM_ID = REF_PRODUCT_FAMILY.BILL_SYSTEM_ID
AND DIM_HIERARCHY.PRODUCT_FAMILY_ID = REF_PRODUCT_FAMILY.PRODUCT_FAMILY_ID
AND DIM_HIERARCHY.BILL_SYSTEM_ID = REF_PROD_TYPE.BILL_SYSTEM_ID
AND DIM_HIERARCHY.PRODUCT_TYPE_ID = REF_PROD_TYPE.PRODUCT_TYPE_ID
AND DIM_HIERARCHY.BILL_SYSTEM_ID = REF_TRANS_CODE.BILL_SYSTEM_ID
AND FACT_TAX.TRANSCODE_ID = REF_TRANS_CODE.TRANS_CODE_ID
AND DIM_HIERARCHY.BILL_SYSTEM_ID = REF_CHARGE_GROUP.BILL_SYSTEM_ID
AND FACT_TAX.CHARGE_GROUP_ID = REF_CHARGE_GROUP.CHARGE_GROUP_ID
AND FACT_TAX.BILL_SYSTEM_ID = REF_STCNTRY.BILL_SYSTEM_ID
AND FACT_TAX.STCNTRY_ID = REF_STCNTRY.STCNTRY_ID
AND FACT_TAX.TAX_ID = REF_TAX.TAX_ID
AND FACT_TAX.BILL_SYSTEM_ID = REF_TAX.BILL_SYSTEM_ID
AND DIM_HIERARCHY.ACCT_ID = DIM_LOCATION.ACCT_ID (+)
AND DIM_HIERARCHY.BILL_SYSTEM_ID = DIM_LOCATION.BILL_SYSTEM_ID (+)
AND DIM_HIERARCHY.SERVICE_ID = DIM_LOCATION.SERVICE_ID (+)
AND DIM_HIERARCHY.ACCT_PART_KEY = DIM_LOCATION.ACCT_PART_KEY (+)
AND DIM_HIERARCHY.BILL_SYSTEM_ID = REF_BPI_PROVIDER.BILL_SYSTEM_ID (+)
AND DIM_HIERARCHY.PROVIDER_ID = REF_BPI_PROVIDER.SVC_PRVDR_ID (+)
AND DIM_HIERARCHY.ACCT_ID = DIM_SUB_ADDL_INFO.ACCT_ID (+)
AND DIM_HIERARCHY.GROUP_ID = DIM_SUB_ADDL_INFO.GROUP_ID (+)
AND DIM_HIERARCHY.SUB_ACCT_ID = DIM_SUB_ADDL_INFO.SUB_ACCT_ID (+)
AND DIM_HIERARCHY.BILL_SYSTEM_ID = DIM_SUB_ADDL_INFO.BILL_SYSTEM_ID (+)
ORDER BY TEMP_DCS.ACCT_ID, TEMP_DCS.INVOICE_NUM, TEMP_DCS.INV_DATE, DIM_HIERARCHY.GROUP_ID, DIM_HIERARCHY.SUB_ACCT_ID, DIM_HIERARCHY.SERVICE_ID) a) WHERE rnum > 0
and rnum <= 10000
Your inner query has multiple columns with the same names, albeit from different tables; those seem to be:
ACCT_ID (from DIM_HIERARCHY and TEMP_DCS)
CHARGE_GROUP_ID
INV_DATE
INVOICE_NUM
PRODUCT_TYPE_ID
The outer query can't cope with that ambiguity. You need to alias the clashing columns so the names are unique in the outer query.
As a simple demo of the issue:
SELECT *
FROM
(SELECT a.* ,
ROWNUM rnum
FROM
(
-- replacing your entire inner query with somethign simple
select dummy, dummy from dual
) a) WHERE rnum > 0
and rnum <= 10000;
SQL Error: ORA-00918: column ambiguously defined
00918. 00000 - "column ambiguously defined"
If you alias the columns the issue goes away:
SELECT *
FROM
(SELECT a.* ,
ROWNUM rnum
FROM
(
-- replacing your entire inner query with somethign simple
select dummy as dummy1, dummy as dumym2 from dual
) a) WHERE rnum > 0
and rnum <= 10000;
D D RNUM
- - ----------
X X 1
You want your pagination query (if using rownum) to be in the form of:
select *
from ( select /*+ FIRST_ROWS(n) */
a.*, ROWNUM rnum
from ( your_query_goes_here,
with order by ) a
where ROWNUM <=
:MAX_ROW_TO_FETCH )
where rnum >= :MIN_ROW_TO_FETCH;
You seem to stick both the upper and lower limits in the same place (among other things). You have:
SELECT *
FROM
(SELECT a.* ,
ROWNUM rnum
FROM
(
select ...
ORDER BY TEMP_DCS.ACCT_ID, TEMP_DCS.INVOICE_NUM, TEMP_DCS.INV_DATE, DIM_HIERARCHY.GROUP_ID, DIM_HIERARCHY.SUB_ACCT_ID, DIM_HIERARCHY.SERVICE_ID) a)
WHERE rnum > 0 and rnum <= 10000
You probably want:
select *
from ( select a.*, ROWNUM rnum
from ( select ... from ... ORDER BY ...) a
where ROWNUM <= 10000 )
where rnum >= 0;

Distinct keyword not fetching results in Oracle

I have the following query where I unique records for patient_id, meaning patient_id should not be duplicate. Each time I try executing the query, seems like the DB hangs or it takes hours to execute, I'm not sure. I need my records to load quickly. Any quick resolution will be highly appreciated.
SELECT DISTINCT a.patient_id,
a.study_id,
a.procstep_id,
a.formdata_seq,
0,
(SELECT MAX(audit_id)
FROM audit_info
WHERE patient_id =a.patient_id
AND study_id = a.study_id
AND procstep_id = a.procstep_id
AND formdata_seq = a.formdata_seq
) AS data_session_id
FROM frm_rg_ps_rg a,
PATIENT_STUDY_STEP pss
WHERE ((SELECT COUNT(*)
FROM frm_rg_ps_rg b
WHERE a.patient_id = b.patient_id
AND a.formdata_seq = b.formdata_seq
AND a.psdate IS NOT NULL
AND b.psdate IS NOT NULL
AND a.psresult IS NOT NULL
AND b.psresult IS NOT NULL) = 1)
OR NOT EXISTS
(SELECT *
FROM frm_rg_ps_rg c
WHERE a.psdate IS NOT NULL
AND c.psdate IS NOT NULL
AND a.psresult IS NOT NULL
AND c.psresult IS NOT NULL
AND a.patient_id = c.patient_id
AND a.formdata_seq = c.formdata_seq
AND a.elemdata_seq! =c.elemdata_seq
AND a.psresult != c.psresult
AND ((SELECT (a.psdate - c.psdate) FROM dual)>=7
OR (SELECT (a.psdate - c.psdate) FROM dual) <=-7)
)
AND a.psresult IS NOT NULL
AND a.psdate IS NOT NULL;
For start, you have a cartesian product with PATIENT_STUDY_STEP (pss).
It is not connected to anything.
select *
from (select t.*
,count (*) over (partition by patient_id) as cnt
from frm_rg_ps_rg t
) t
where cnt = 1
;

Efficiently writing this formula in SQL server 2008

Say I have table and these are its sample rows
ChangeID Change
1 102
2 105
3 107
4 110
The change formula is
(CurrentRowChange - PreviousRowChange) / PreviousRowChange
Hence:
for 1st row it should be 0
for 2nd row it should be (105 - 102) / 102
and so on. How can I efficiently write this formula in SQL?
I know I can write a scalar function and then do a RowNumber and order By ChangeID and fetch the row number's Change value and then find the current row number - 1 and then fetch that row's Change value and do a divide.
Is there any better way to achieve this?
give this a try, assuming that CHANGEID can be deleted and it is IDENTITY.
WITH changeList
AS
(
SELECT ChangeID, [Change],
(ROW_NUMBER() OVER (ORDER BY ChangeID ASC)) -1 AS rn
FROM TableName
),
normalList
AS
(
SELECT ChangeID, [Change],
(ROW_NUMBER() OVER (ORDER BY ChangeID ASC)) AS rn
FROM TableName
)
SELECT a.ChangeID, a.[Change],
COALESCE((a.Change - b.change) / (b.change * 1.0),0) result
FROM changeList a
LEFT JOIN normalList b
ON a.rn = b.rn
SQLFiddle Demo
select cur.*
, case
when prev.ChangeId is null then 0
else 1.0 * (cur.Change - prev.Change) / prev.Change
end
from Table1 cur
left join
Table1 prev
on cur.ChangeId = prev.ChangeId + 1
SQL Fiddle example.
While the ChangeID's are sequential in the sample, I wouldn't assume that they always are. So I would do something like this:
with RankedIDs as
select ChangeID
, Change
, rank() over
(partition by ChangeID order by ChangeId) rank
where something maybe ;
select case
when r1.rank = 1 then 0
else (r1.change - r2.change) / r2.change
end SomeName
from RankedIds r1 join RankedIds r2 on r1.rank = r2.rank + 1
That's the basic idea. You might want to add divide by zero protection
select T1.ChangeID,
(1.0 * T1.Change / T2.Change) - 1 as Result
from TableName as T1
outer apply (
select top(1) T.Change
from TableName as T
where T.ChangeID < T1.ChangeID
order by T.ChangeID desc
) as T2

how to limit a sql integer query result to <=1

how to limit an integer query result to 1. a return of 2 to be 1, a return 1 to be 1, and a return of 0.5 to be 0.5 because it is <= 1. i don't want to modify the tables, i just want to modify the results.
This is my exact query.
select ((select "V01" from sports where "UID" = '1') * 1.0 ) /
(select "V01" from master where "BALL" = 'REQUIREMENT') ;
I'm using postgres.
To limit, you'd do something like this:
select
case
when yourNumber >= 1 then 1
else yourNumber
end
...
Then you just apply this concept to your query.
As noted by Wiseguy, you could also do:
select LEAST(yourNumber, 1)
, since this is postgresql.
The first solution will work with any ANSI SQL compatible database.
Update
Applied to your query, I think (if I understood what you want correctly) it would be like this:
select LEAST(1,
((select "V01" from sports where "UID" = '1') * 1.0 ) /
(select "V01" from master where "BALL" = 'REQUIREMENT')
);
use the LEAST function , docs: http://www.postgresql.org/docs/8.3/static/functions-conditional.html. Also, check out GREATEST too
SELECT LEAST(1, <your value>)
EDIT replaced GREATEST with LEAST
try this:
select CASE
WHEN ((select V01 from sports where UID = '1') * 1.0 ) /
(select V01 from master where BALL = 'REQUIREMENT') >= 1
THEN 1
ELSE ((select V01 from sports where UID = '1') * 1.0 ) /
(select V01 from master where BALL = 'REQUIREMENT')
END;