Min/Max timestamp of a slow changing dimension
I'm having some thoughts on an SQL (Redshift) query I need. So basically, I have the following table
userid | timestamp | fruit
1 | 2018-12-10T14:46:50 | banana
1 | 2018-12-10T15:46:50 | banana
1 | 2018-12-10T16:46:50 | apple
1 | 2018-12-10T17:46:50 | banana
Would it be possible to come up with a new table with the following information
userid | start | end | fruit
1 | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | banana
1 | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | apple
1 | 2018-12-10T17:46:50 | | banana
showing the time range where the user kept his favorite fruit selection.
Thanks in advance!
D
sql amazon-redshift gaps-and-islands
add a comment |
I'm having some thoughts on an SQL (Redshift) query I need. So basically, I have the following table
userid | timestamp | fruit
1 | 2018-12-10T14:46:50 | banana
1 | 2018-12-10T15:46:50 | banana
1 | 2018-12-10T16:46:50 | apple
1 | 2018-12-10T17:46:50 | banana
Would it be possible to come up with a new table with the following information
userid | start | end | fruit
1 | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | banana
1 | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | apple
1 | 2018-12-10T17:46:50 | | banana
showing the time range where the user kept his favorite fruit selection.
Thanks in advance!
D
sql amazon-redshift gaps-and-islands
add a comment |
I'm having some thoughts on an SQL (Redshift) query I need. So basically, I have the following table
userid | timestamp | fruit
1 | 2018-12-10T14:46:50 | banana
1 | 2018-12-10T15:46:50 | banana
1 | 2018-12-10T16:46:50 | apple
1 | 2018-12-10T17:46:50 | banana
Would it be possible to come up with a new table with the following information
userid | start | end | fruit
1 | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | banana
1 | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | apple
1 | 2018-12-10T17:46:50 | | banana
showing the time range where the user kept his favorite fruit selection.
Thanks in advance!
D
sql amazon-redshift gaps-and-islands
I'm having some thoughts on an SQL (Redshift) query I need. So basically, I have the following table
userid | timestamp | fruit
1 | 2018-12-10T14:46:50 | banana
1 | 2018-12-10T15:46:50 | banana
1 | 2018-12-10T16:46:50 | apple
1 | 2018-12-10T17:46:50 | banana
Would it be possible to come up with a new table with the following information
userid | start | end | fruit
1 | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | banana
1 | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | apple
1 | 2018-12-10T17:46:50 | | banana
showing the time range where the user kept his favorite fruit selection.
Thanks in advance!
D
sql amazon-redshift gaps-and-islands
sql amazon-redshift gaps-and-islands
edited Jan 1 at 20:51
Barbaros Özhan
13.7k71633
13.7k71633
asked Jan 1 at 17:48
SunSatIONSunSatION
384
384
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
It's a typical gaps and islands
problem, lag
and lead
analytic functions might be used as follows:
with fruits(userid,timestamp,fruit) as (
values
(1,'2018-12-10T14:46:50','banana'),
(1,'2018-12-10T15:46:50','banana'),
(1,'2018-12-10T16:46:50','apple'),
(1,'2018-12-10T17:46:50','banana')
)
select userid, min(timestamp) as start, max(ld) as end, fruit
from
(
select f2.*,
sum(case when lg = fruit then 0 else 1 end) over
(partition by userid, fruit order by timestamp) sm
from
(
select f1.*,
lead(timestamp) over (partition by userid order by timestamp) as ld,
lag(fruit) over (partition by userid order by timestamp) as lg
from fruits f1
) f2
) f
group by userid, fruit, sm
order by start;
userid start end fruit
------- ------------------- ------------------- ------
1 2018-12-10T14:46:50 2018-12-10T16:46:50 banana
1 2018-12-10T16:46:50 2018-12-10T17:46:50 apple
1 2018-12-10T17:46:50 NULL banana
Rextester Demo
Unfortunately this will not work when the user reselect the same favorite twice due to the group by allowing a single row for each result, and sm can be the same twice
– SunSatION
Jan 3 at 15:42
@SunSatION I show on the Demo that this query works. Please share samples to show what exactly you mean.
– Barbaros Özhan
Jan 3 at 16:25
add a comment |
Schema (MySQL v8.0)
CREATE TABLE t1 (
`userid` INTEGER,
`timestamp` VARCHAR(19),
`fruit` VARCHAR(6)
);
INSERT INTO t1
(`userid`, `timestamp`, `fruit`)
VALUES
('1', '2018-12-10T14:46:50', 'banana'),
('1', '2018-12-10T15:46:50', 'banana'),
('1', '2018-12-10T16:46:50', 'apple'),
('1', '2018-12-10T17:46:50', 'banana');
Query #1
Simple approach if you dont mind multiple records for consecutive fruits
select userid, fruit, timestamp `start`,
lead(timestamp) over (order by timestamp) `end`
from t1;
| userid | fruit | start | end |
| ------ | ------ | ------------------- | ------------------- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T15:46:50 |
| 1 | banana | 2018-12-10T15:46:50 | 2018-12-10T16:46:50 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 |
| 1 | banana | 2018-12-10T17:46:50 | |
Or
Query #2
SELECT t2.*
FROM (
SELECT userid,
fruit,
timestamp `tstart`,
CASE
WHEN fruit = Lead(fruit) over(ORDER BY timestamp) THEN lead(timestamp, 2) over ( ORDER BY timestamp)
ELSE lead(timestamp, 1) over ( ORDER BY timestamp)
end `tend`,
CASE
WHEN fruit = lag(fruit) over (ORDER BY timestamp) THEN 1
ELSE 0
end del
FROM t1 ) t2
WHERE del = 0;
| userid | fruit | tstart | tend | del |
| ------ | ------ | ------------------- | ------------------- | --- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | 0 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | 0 |
| 1 | banana | 2018-12-10T17:46:50 | | 0 |
View on DB Fiddle
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997622%2fmin-max-timestamp-of-a-slow-changing-dimension%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
It's a typical gaps and islands
problem, lag
and lead
analytic functions might be used as follows:
with fruits(userid,timestamp,fruit) as (
values
(1,'2018-12-10T14:46:50','banana'),
(1,'2018-12-10T15:46:50','banana'),
(1,'2018-12-10T16:46:50','apple'),
(1,'2018-12-10T17:46:50','banana')
)
select userid, min(timestamp) as start, max(ld) as end, fruit
from
(
select f2.*,
sum(case when lg = fruit then 0 else 1 end) over
(partition by userid, fruit order by timestamp) sm
from
(
select f1.*,
lead(timestamp) over (partition by userid order by timestamp) as ld,
lag(fruit) over (partition by userid order by timestamp) as lg
from fruits f1
) f2
) f
group by userid, fruit, sm
order by start;
userid start end fruit
------- ------------------- ------------------- ------
1 2018-12-10T14:46:50 2018-12-10T16:46:50 banana
1 2018-12-10T16:46:50 2018-12-10T17:46:50 apple
1 2018-12-10T17:46:50 NULL banana
Rextester Demo
Unfortunately this will not work when the user reselect the same favorite twice due to the group by allowing a single row for each result, and sm can be the same twice
– SunSatION
Jan 3 at 15:42
@SunSatION I show on the Demo that this query works. Please share samples to show what exactly you mean.
– Barbaros Özhan
Jan 3 at 16:25
add a comment |
It's a typical gaps and islands
problem, lag
and lead
analytic functions might be used as follows:
with fruits(userid,timestamp,fruit) as (
values
(1,'2018-12-10T14:46:50','banana'),
(1,'2018-12-10T15:46:50','banana'),
(1,'2018-12-10T16:46:50','apple'),
(1,'2018-12-10T17:46:50','banana')
)
select userid, min(timestamp) as start, max(ld) as end, fruit
from
(
select f2.*,
sum(case when lg = fruit then 0 else 1 end) over
(partition by userid, fruit order by timestamp) sm
from
(
select f1.*,
lead(timestamp) over (partition by userid order by timestamp) as ld,
lag(fruit) over (partition by userid order by timestamp) as lg
from fruits f1
) f2
) f
group by userid, fruit, sm
order by start;
userid start end fruit
------- ------------------- ------------------- ------
1 2018-12-10T14:46:50 2018-12-10T16:46:50 banana
1 2018-12-10T16:46:50 2018-12-10T17:46:50 apple
1 2018-12-10T17:46:50 NULL banana
Rextester Demo
Unfortunately this will not work when the user reselect the same favorite twice due to the group by allowing a single row for each result, and sm can be the same twice
– SunSatION
Jan 3 at 15:42
@SunSatION I show on the Demo that this query works. Please share samples to show what exactly you mean.
– Barbaros Özhan
Jan 3 at 16:25
add a comment |
It's a typical gaps and islands
problem, lag
and lead
analytic functions might be used as follows:
with fruits(userid,timestamp,fruit) as (
values
(1,'2018-12-10T14:46:50','banana'),
(1,'2018-12-10T15:46:50','banana'),
(1,'2018-12-10T16:46:50','apple'),
(1,'2018-12-10T17:46:50','banana')
)
select userid, min(timestamp) as start, max(ld) as end, fruit
from
(
select f2.*,
sum(case when lg = fruit then 0 else 1 end) over
(partition by userid, fruit order by timestamp) sm
from
(
select f1.*,
lead(timestamp) over (partition by userid order by timestamp) as ld,
lag(fruit) over (partition by userid order by timestamp) as lg
from fruits f1
) f2
) f
group by userid, fruit, sm
order by start;
userid start end fruit
------- ------------------- ------------------- ------
1 2018-12-10T14:46:50 2018-12-10T16:46:50 banana
1 2018-12-10T16:46:50 2018-12-10T17:46:50 apple
1 2018-12-10T17:46:50 NULL banana
Rextester Demo
It's a typical gaps and islands
problem, lag
and lead
analytic functions might be used as follows:
with fruits(userid,timestamp,fruit) as (
values
(1,'2018-12-10T14:46:50','banana'),
(1,'2018-12-10T15:46:50','banana'),
(1,'2018-12-10T16:46:50','apple'),
(1,'2018-12-10T17:46:50','banana')
)
select userid, min(timestamp) as start, max(ld) as end, fruit
from
(
select f2.*,
sum(case when lg = fruit then 0 else 1 end) over
(partition by userid, fruit order by timestamp) sm
from
(
select f1.*,
lead(timestamp) over (partition by userid order by timestamp) as ld,
lag(fruit) over (partition by userid order by timestamp) as lg
from fruits f1
) f2
) f
group by userid, fruit, sm
order by start;
userid start end fruit
------- ------------------- ------------------- ------
1 2018-12-10T14:46:50 2018-12-10T16:46:50 banana
1 2018-12-10T16:46:50 2018-12-10T17:46:50 apple
1 2018-12-10T17:46:50 NULL banana
Rextester Demo
answered Jan 1 at 20:48
Barbaros ÖzhanBarbaros Özhan
13.7k71633
13.7k71633
Unfortunately this will not work when the user reselect the same favorite twice due to the group by allowing a single row for each result, and sm can be the same twice
– SunSatION
Jan 3 at 15:42
@SunSatION I show on the Demo that this query works. Please share samples to show what exactly you mean.
– Barbaros Özhan
Jan 3 at 16:25
add a comment |
Unfortunately this will not work when the user reselect the same favorite twice due to the group by allowing a single row for each result, and sm can be the same twice
– SunSatION
Jan 3 at 15:42
@SunSatION I show on the Demo that this query works. Please share samples to show what exactly you mean.
– Barbaros Özhan
Jan 3 at 16:25
Unfortunately this will not work when the user reselect the same favorite twice due to the group by allowing a single row for each result, and sm can be the same twice
– SunSatION
Jan 3 at 15:42
Unfortunately this will not work when the user reselect the same favorite twice due to the group by allowing a single row for each result, and sm can be the same twice
– SunSatION
Jan 3 at 15:42
@SunSatION I show on the Demo that this query works. Please share samples to show what exactly you mean.
– Barbaros Özhan
Jan 3 at 16:25
@SunSatION I show on the Demo that this query works. Please share samples to show what exactly you mean.
– Barbaros Özhan
Jan 3 at 16:25
add a comment |
Schema (MySQL v8.0)
CREATE TABLE t1 (
`userid` INTEGER,
`timestamp` VARCHAR(19),
`fruit` VARCHAR(6)
);
INSERT INTO t1
(`userid`, `timestamp`, `fruit`)
VALUES
('1', '2018-12-10T14:46:50', 'banana'),
('1', '2018-12-10T15:46:50', 'banana'),
('1', '2018-12-10T16:46:50', 'apple'),
('1', '2018-12-10T17:46:50', 'banana');
Query #1
Simple approach if you dont mind multiple records for consecutive fruits
select userid, fruit, timestamp `start`,
lead(timestamp) over (order by timestamp) `end`
from t1;
| userid | fruit | start | end |
| ------ | ------ | ------------------- | ------------------- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T15:46:50 |
| 1 | banana | 2018-12-10T15:46:50 | 2018-12-10T16:46:50 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 |
| 1 | banana | 2018-12-10T17:46:50 | |
Or
Query #2
SELECT t2.*
FROM (
SELECT userid,
fruit,
timestamp `tstart`,
CASE
WHEN fruit = Lead(fruit) over(ORDER BY timestamp) THEN lead(timestamp, 2) over ( ORDER BY timestamp)
ELSE lead(timestamp, 1) over ( ORDER BY timestamp)
end `tend`,
CASE
WHEN fruit = lag(fruit) over (ORDER BY timestamp) THEN 1
ELSE 0
end del
FROM t1 ) t2
WHERE del = 0;
| userid | fruit | tstart | tend | del |
| ------ | ------ | ------------------- | ------------------- | --- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | 0 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | 0 |
| 1 | banana | 2018-12-10T17:46:50 | | 0 |
View on DB Fiddle
add a comment |
Schema (MySQL v8.0)
CREATE TABLE t1 (
`userid` INTEGER,
`timestamp` VARCHAR(19),
`fruit` VARCHAR(6)
);
INSERT INTO t1
(`userid`, `timestamp`, `fruit`)
VALUES
('1', '2018-12-10T14:46:50', 'banana'),
('1', '2018-12-10T15:46:50', 'banana'),
('1', '2018-12-10T16:46:50', 'apple'),
('1', '2018-12-10T17:46:50', 'banana');
Query #1
Simple approach if you dont mind multiple records for consecutive fruits
select userid, fruit, timestamp `start`,
lead(timestamp) over (order by timestamp) `end`
from t1;
| userid | fruit | start | end |
| ------ | ------ | ------------------- | ------------------- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T15:46:50 |
| 1 | banana | 2018-12-10T15:46:50 | 2018-12-10T16:46:50 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 |
| 1 | banana | 2018-12-10T17:46:50 | |
Or
Query #2
SELECT t2.*
FROM (
SELECT userid,
fruit,
timestamp `tstart`,
CASE
WHEN fruit = Lead(fruit) over(ORDER BY timestamp) THEN lead(timestamp, 2) over ( ORDER BY timestamp)
ELSE lead(timestamp, 1) over ( ORDER BY timestamp)
end `tend`,
CASE
WHEN fruit = lag(fruit) over (ORDER BY timestamp) THEN 1
ELSE 0
end del
FROM t1 ) t2
WHERE del = 0;
| userid | fruit | tstart | tend | del |
| ------ | ------ | ------------------- | ------------------- | --- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | 0 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | 0 |
| 1 | banana | 2018-12-10T17:46:50 | | 0 |
View on DB Fiddle
add a comment |
Schema (MySQL v8.0)
CREATE TABLE t1 (
`userid` INTEGER,
`timestamp` VARCHAR(19),
`fruit` VARCHAR(6)
);
INSERT INTO t1
(`userid`, `timestamp`, `fruit`)
VALUES
('1', '2018-12-10T14:46:50', 'banana'),
('1', '2018-12-10T15:46:50', 'banana'),
('1', '2018-12-10T16:46:50', 'apple'),
('1', '2018-12-10T17:46:50', 'banana');
Query #1
Simple approach if you dont mind multiple records for consecutive fruits
select userid, fruit, timestamp `start`,
lead(timestamp) over (order by timestamp) `end`
from t1;
| userid | fruit | start | end |
| ------ | ------ | ------------------- | ------------------- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T15:46:50 |
| 1 | banana | 2018-12-10T15:46:50 | 2018-12-10T16:46:50 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 |
| 1 | banana | 2018-12-10T17:46:50 | |
Or
Query #2
SELECT t2.*
FROM (
SELECT userid,
fruit,
timestamp `tstart`,
CASE
WHEN fruit = Lead(fruit) over(ORDER BY timestamp) THEN lead(timestamp, 2) over ( ORDER BY timestamp)
ELSE lead(timestamp, 1) over ( ORDER BY timestamp)
end `tend`,
CASE
WHEN fruit = lag(fruit) over (ORDER BY timestamp) THEN 1
ELSE 0
end del
FROM t1 ) t2
WHERE del = 0;
| userid | fruit | tstart | tend | del |
| ------ | ------ | ------------------- | ------------------- | --- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | 0 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | 0 |
| 1 | banana | 2018-12-10T17:46:50 | | 0 |
View on DB Fiddle
Schema (MySQL v8.0)
CREATE TABLE t1 (
`userid` INTEGER,
`timestamp` VARCHAR(19),
`fruit` VARCHAR(6)
);
INSERT INTO t1
(`userid`, `timestamp`, `fruit`)
VALUES
('1', '2018-12-10T14:46:50', 'banana'),
('1', '2018-12-10T15:46:50', 'banana'),
('1', '2018-12-10T16:46:50', 'apple'),
('1', '2018-12-10T17:46:50', 'banana');
Query #1
Simple approach if you dont mind multiple records for consecutive fruits
select userid, fruit, timestamp `start`,
lead(timestamp) over (order by timestamp) `end`
from t1;
| userid | fruit | start | end |
| ------ | ------ | ------------------- | ------------------- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T15:46:50 |
| 1 | banana | 2018-12-10T15:46:50 | 2018-12-10T16:46:50 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 |
| 1 | banana | 2018-12-10T17:46:50 | |
Or
Query #2
SELECT t2.*
FROM (
SELECT userid,
fruit,
timestamp `tstart`,
CASE
WHEN fruit = Lead(fruit) over(ORDER BY timestamp) THEN lead(timestamp, 2) over ( ORDER BY timestamp)
ELSE lead(timestamp, 1) over ( ORDER BY timestamp)
end `tend`,
CASE
WHEN fruit = lag(fruit) over (ORDER BY timestamp) THEN 1
ELSE 0
end del
FROM t1 ) t2
WHERE del = 0;
| userid | fruit | tstart | tend | del |
| ------ | ------ | ------------------- | ------------------- | --- |
| 1 | banana | 2018-12-10T14:46:50 | 2018-12-10T16:46:50 | 0 |
| 1 | apple | 2018-12-10T16:46:50 | 2018-12-10T17:46:50 | 0 |
| 1 | banana | 2018-12-10T17:46:50 | | 0 |
View on DB Fiddle
answered Jan 1 at 18:53
SimonareSimonare
14.8k11840
14.8k11840
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53997622%2fmin-max-timestamp-of-a-slow-changing-dimension%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown