Retrieving of Specific Age Group - mysql

I want to ask some help on SQL Query on how to retrieve bookings with specific age group. Basically, i want to retrieve bookings where there are customers who are Adults and child, these are determined only by date of birth. Children are treated as 15 years old below and adults are more than 15 years of age. I want to retrieve bookings who have children and adults that does not exceed 20yrs of age. No bookings should be retrieve if there is one customer in the booking that has age of more than 20 yrs old. And bookings should have more than 1 customer. Here's a sample table for your reference -
Booking No 123
Customer 1 - March 1, 2008
Customer 2 - Aug 3, 1998
Booking No 456
Customer 1 - March 2, 1986
Customer 2 - Feb 9, 2007
Customer 3 - Apr 10, 1999
Booking No 789
Customer 1 - Jun 7, 1999
The booking that needs to be retrieved is only Booking No 123. No age is provided in the table and computed only using Date of birth - DateDiff.
BookingID
CustomerID
LName
FName
DOB
ReservationID
BookingID
CompanyID
ArrivalDate
CompanyName
This is the where statement that i've put
(SELECT DATEDIFF(YEAR ,bp.DOB,GETDATE())) <= 20 AND (SELECT DATEDIFF(YEAR ,bp.DOB,GETDATE())) < 15
But still pulling bookings containing customers > 20 yrs old.

This should get you the bookings. The date computation should be based on the RESERVATION Arrival Date, as such if considering older or future reservations, getdate() WOULD alter the computed age at the time of arrival.
I am doing a direct join between the reservation and booking tables grouped by booking and qualifying every occupant's age.
SELECT
R.BookingID
FROM
BookingCustomer BC
JOIN Reservation R
ON BC.BookingID = R.BookingID
group by
R.BookingID
having
SUM( case when DATEDIFF(YEAR , BC.DOB, R.ArrivalDate ) < 16 then 1 else 0 end ) > 0
AND SUM( case when DATEDIFF(YEAR , BC.DOB, R.ArrivalDate ) >= 16
and DATEDIFF(YEAR , BC.DOB, R.ArrivalDate ) < 21 then 1 else 0 end ) > 0
AND SUM( case when DATEDIFF(YEAR , BC.DOB, R.ArrivalDate ) > 20 then 1 else 0 end ) = 0
Now, since a booking is all pointing to a same reservation, you COULD grab all the other fields at the same time
SELECT
R.BookingID,
R.ReservationID,
R.CompanyID,
R.ArrivalDate,
R.CompanyName ... rest of query.
If the query nags about non-aggregate fields, you could just wrap the other fields not part of the group by as MAX() since a booking is always pointing to the same respective reservation and the parent reservation details would not change anyhow.
SELECT
R.BookingID,
MAX( R.ReservationID ) ReservationID,
MAX( R.CompanyID ) CompanyID,
MAX( R.ArrivalDate ) ArrivalDate,
MAX( R.CompanyName ) CompanyName ... rest of query.

Okay, now we can see what's going on (and what's going wrong for you).
Your current query has this:
WHERE (SELECT DATEDIFF(YEAR ,bp.DOB,GETDATE()) <= 20
AND (SELECT DATEDIFF(YEAR ,bp.DOB,GETDATE())) < 15
...this can be translated to:
WHERE (the number of times January 1st is passed) <= 20
AND AT THE SAME TIME (the number of times January 1st is passed) < 15
Besides the fact that ANDs are exclusive - rows have to match both conditions - what's going on is that DATEDIFF counts the number of "boundaries" crossed for the given measure:
Returns the count (signed integer) of the specified datepart boundaries crossed between the specified startdate and enddate.
... and of course the boundary for a year would be January 1st.
First, a digression on range-searching on database. What you do this, WHERE DATEDIFF(YEAR ,bp.DOB,GETDATE() <= 20, you usually cause the database to ignore indices, which are ways to speed up queries; this is because it has to calculate a value (here, the difference in the year), for each row in the table (because otherwise it doesn't know if the calculated value matches).
Instead, it's better to do any "math", whenever possible, on constant values, since the database is going to remember them. The form we should use here will also solve the "selecting older customers" problem too:
WHERE DOB <= DATEADD(year, -21, GETDATE())
(This is equivalent to those "you are 21 if you were born on or before this date in the year XXXX" signs you see in grocery stores)
No that that's out of the way, we need to figure out what we actually need. Restating your conditions above, we're looking for bookings with (all of):
At least one customer 20 years or younger
At least one customer younger than 15 years
No customers more than 20 years old
At least two customers.
Now... Presumably we don't care about multiple (or single) customers that are younger than 20 years old, so long as they're also all more than 15 years old, so we should modify the first condition. Also, quite probably we need to warn if there are only customers in a booking who are 15 years or younger - they don't even have an "almost" adult! And quite probably we need to warn if this person would be all alone, too! So the conditions should be changed to:
At least one customer younger than 15 years
No customers 21 years or older
(please tell me if this restatement was incorrect)
Now that we no our conditions, we can write our statement. We are looking for bookings:
SELECT ReservationID, BookingID, CompanyID, ArrivalDate, CompanyName
FROM Booking
Where there is at least one customer younger than 15 years:
WHERE EXISTS (SELECT 1
FROM BookingCustomer
WHERE BookingCustomer.bookingId = Booking.BookingId
-- birthday after 15 years ago today
AND BookingCustomer.dob > DATEADD(year, -15, GETDATE()))
And there is also no customer 21 years or older:
AND NOT EXISTS (SELECT 1
FROM BookingCustomer
WHERE BookingCustomer.bookingId = Booking.BookingId
-- birthday before or on 21 years ago today
AND BookingCustomer.dob <= DATEADD(year, -21, GETDATE()))
side note: most of the time for booked tours and stuff, they only care about ages at the time the trip is taken, not the booking time, or whatever "today" happens to be when you run this. You probably don't want GETDATE(), but something else, likely ArrivalDate. Since you'd be doing math on a column it would again force a table scan, but keeping the age check - and modifying it a bit to take into account how far ahead a booking can be made - would knock out bookings "earlier" because somebody is definitely old enough (or nobody young enough).

Thanks for the detailed response. I tried the suggested query and it's not returning any booking
WHERE EXISTS (SELECT 1
FROM BookingCustomer
WHERE BookingCustomer.bookingId = Booking.BookingId
-- birthday after 15 years ago today
OR BookingCustomer.dob > DATEADD(year, -15, BOOKING.ARRIVALDATE))
AND NOT EXISTS (SELECT 1
FROM BookingCustomer
WHERE BookingCustomer.bookingId = Booking.BookingId
-- birthday before or on 21 years ago today
AND BookingCustomer.dob <= DATEADD(year, -21, BOOKING.ARRIVALDATE))

Related

MySQL - Way to simplify repetitive calculation sub-queries

I've been tasked with making output that fetches number of days passed between an order and its shipment, like this:
order_date
orders
Days0
Days1
Days7Plus
2022-11-01
12
9
3
1
2022-11-15
22
20
0
2
2022-12-02
77
65
5
7
I'm sure you can imagine example underlying data, where there's an orders table with a unique ID per record, an order date that can share multiple IDs, and each order has its own ship date.
The hard part is counting only business days, which required subtracting weekends and holidays from the date range days. I got that all figured out but it required copy-pasting these ugly sub-queries 7 more times :/ While this can be dynamically generated in other code, I figured there must be a cleaner way, since other people (some non-devs) may be testing or reviewing this, and I'll probably get grief about it.
Here's the query essentially:
# get orders shipped count
SELECT
...
# orders that were shipped x number of days from receipt
SUM(COALESCE(DATEDIFF(shipped, ordered), 0)
- ( # subtract weekend days
5 * (DATEDIFF('2022-12-05', '2022-11-01') DIV 7)
+ MID('0123444401233334012222340111123400012345001234550',
7 * WEEKDAY('2022-11-01') + WEEKDAY('2022-12-05') + 1, 1
)
)
- ( # subtract holidays
SELECT COUNT(`date`) FROM holiday WHERE active = 1
AND `date` BETWEEN '2022-11-01' AND '2022-12-05'
AND DAYOFWEEK(`date`) < 6
)
= 0) AS 0Days, # subsequently 1Days, 2Days, 3Days, etc
...
SUM(COALESCE(DATEDIFF(shipped, ordered), 0)
- ( # subtract weekend days
5 * (DATEDIFF('2022-12-05', '2022-11-01') DIV 7)
+ MID('0123444401233334012222340111123400012345001234550',
7 * WEEKDAY('2022-11-01') + WEEKDAY('2022-12-05') + 1, 1
)
)
- ( # subtract holidays
SELECT COUNT(`date`) FROM holiday WHERE active = 1
AND `date` BETWEEN '2022-11-01' AND '2022-12-05'
AND DAYOFWEEK(`date`) < 6
)
>= 7) AS Days7Plus
FROM orders
WHERE
AND ordered BETWEEN :startDate AND :endDate
GROUP BY CAST(ordered AS DATE)
ORDER BY ordered
I got the MID calculation from https://stackoverflow.com/a/6762805/14744970
I feel pretty proud of getting it all together, but I feel like I'm a small step away from collapsing the redundancy down somehow that I'm not quite understanding.
Note that I don't know if the GROUP BY actually matters with any sort of simplifying of the redundant statements.

How to query available item leases based on a date range in MySQL?

We have a business that rents out international phone numbers to customers when traveling. When a customer makes an order We want to display to the customer the available phone numbers for his booking dates based on his start_date and end_date and numbers which is not occupied yet.
Since these phone numbers are rented out, I need to select from the table ONLY those numbers that are not rented out yet for dates that would interfere with the current customers dates.
I also don't want to rent out any phone number prior to 7 days after its end date. Meaning, If a customer booked a phone number for 1-1-2020 through 1-20-2020, I don't want this phone number to be booked by another customer before 1-27-2020. I want the phone number to have a 7 day window of being clear.
I have a table with the phone numbers and a table with the orders that is related to the phone numbers table via phone_number_id. The orders table has the current customers start_date and end_date for travel without the phone number id saved yet to it. The orders table also has the start_date and end_date for all other customers dates of travel as well as which phone_number_id was assigned/booked up for their travel dates.
How would the MySQL query look like when trying to select the phone numbers that are available for the current customers dates?
I build below query at the moment
SELECT x.id
, x.area_code
, x.phone_number
, y.start_date
, y.end_date
FROM vir_num_table x
LEFT
JOIN orderitemsdetail_table y
ON y.vn_id = x.id
WHERE y.start_date BETWEEN '2020-01-11' AND '2020-01-18'
OR y.start_date IS NULL
I've build this query but stuck here how can I add end_date logic.
Any help would be appreciated! Thanks in advance.
The way I'd approach the problem would be to look at conceptually, is as a cross product of the set of all phone numbers, along with the reservation timeframe, and then exclude those where there's a conflicting reservation.
A conflict would be an overlap, existing reservation that has a start_date before the end of the proposed reservation AND has an end_date on or after the start of the proposed reservation.
I'd do an anti-join pattern, something like this:
SELECT pn.phone_number
FROM phone_number pn
LEFT
JOIN reservation rs
ON rs.phone_number = pn.phone_number
AND rs.start_dt <= '2019-12-27' + INTERVAL +7 DAY
AND rs.end_dt > '2019-12-20' + INTERVAL -7 DAY
WHERE rs.phone_number IS NULL
That essentially says get all rows from phone number, along with matching rows from reservations (rows that overlap), but then exclude all the rows that had a match, leaving just phone_number rows that did not have a match.
We can make the < test a <= or , subtract 8 days, to tailor the "7 day" window before; we can tweak as we run the query through the test cases,
We can achieve an equivalent result using a NOT EXISTS and a correlated subquery. Some people find this easier to comprehend than the ant-join, but its essentially the same query, doing the same thing, get all rows from phone_number but exclude the rows where there is a matching (overlapping) row in reservation
SELECT pn.phone_number
FROM phone_number pn
WHERE NOT EXISTS
( SELECT 1
FROM reservation rs
WHERE rs.phone_number = pn.phone_number
AND rs.start_dt <= '2019-12-27' + INTERVAL +7 DAY
AND rs.end_dt > '2019-12-20' + INTERVAL -7 DAY
)
There are several questions on StackOverflow about checking for overlap, or no overlap, of date ranges.
See e.g.
How to check if two date ranges overlap in mysql?
PHP/SQL - How can I check if a date user input is in between an existing date range in my database?
MySQL query to select distinct rows based on date range overlapping
EDIT
Based on the SQL added as an edit to the question, I'd do the query like this:
SELECT pn.`id`
, pn.`area_code`
, pn.`phone_number`
FROM `vir_num_table` pn
LEFT
JOIN `orderitemsdetail_table` rs
ON rs.vn_id = pn.id
AND rs.start_date <= '2020-01-18' + INTERVAL +7 DAY
AND rs.end_date > '2020-01-11' + INTERVAL -7 DAY
WHERE rs.vn_id IS NULL
The two "tricky" parts. First is the anti-join, understanding how that works. (An outer join, to return all rows from vir_num_table but exclude any rows that have a matching row in reservations. The second tricky part is checking for the overlap, coming up with the conditions: r.start <= p.end AND r.end >= p.start, then tweaking whether we want to include the equals as an overlap, and tweaking the extra seven days (easiest to me to just subtract the 7 days from the beginning of the proposed reservation)
... now occurs to me like we need to add a guard period of 7 days on the end of the reservation period as well, doh!
Here's a query plus sorting algo to choose the optimal phone number selection for maximum utilization efficiency (i.e. getting as close as possible to exactly 7 days before and after each use).
I set it to give open ends a weight of 9, so that "near perfect" fits (7-8 days before or after) would be selected ahead of open-ended numbers. This will yield a slight efficiency improvement, as open numbers can accommodate any reservation. You can adjust this for your needs. If you set this to 0, for example, it would always select open numbers first.
SELECT ph.phone_number,
COALESCE(
MIN(
IF(res.end_date > res.start_date > '2020-01-18',
NULL, -- ignore before-comparison for reservations starting and ending after date range
DATEDIFF('2020-01-11', res.end_date)
), 9) AS open_days_before,
COALESCE(
MIN(
IF(res.start_date < res.end_date < '2020-01-11',
NULL, -- ignore after-comparison for reservations starting and ending before date range
DATEDIFF(res.start_date, '2020-01-18')
), 9) AS open_days_after
FROM phone_number ph
LEFT JOIN reservation res
ON res.phone_number = ph.phone_number
AND res.end_date >= CURRENT_DATE() - INTERVAL 6 DAY
GROUP BY ph.phone_number
HAVING open_days_before >= 7
AND open_days_after >= 7
ORDER BY open_days_before + open_days_after
LIMIT 1
Edit: updated to add grouping, because I realize this is an aggregate problem.
Edit 2: bug fix, changed MAX to MIN
Edit 3: added res.end_date >= CURRENT_DATE - INTERVAL 6 DAY to ignore past reservations, limiting aggregate data and treating phone number with no reservations between 6 days ago and the beginning of the new order as "open on the front-end"
Edit 4: added IF conditions to eliminate reservations outside the given before-or-after comparison ranges (e.g. comparing reservations after the selected range from influencing the "open days before" number), to prevent negative numbers, except when there's overlap with the selected range.
Based on the info you've added then you shouldn't need to check the start date of phone numbers which have been booked out.
You customer provides you with a start date and an end date.
You only rent out phone numbers 7 days after their last lease ended
All you need to do is fetch back phone numbers which either:
- Are not rented out and therefor aren't in the orderitems table
- OR have an end_date which is 7 days before the new customer's start date.
Here you go:
SELECT
`main_table`.`id`,
`main_table`.`area_code`,
`main_table`.`phone_number`,
`orderitemsdetail_table`.`start_date`,
`orderitemsdetail_table`.`end_date`
FROM
`vir_num_table` AS `main_table`
LEFT JOIN
`orderitemsdetail_table` AS `orderitemsdetail_table` ON main_table.id = orderitemsdetail_table.vn_id
WHERE
(DATE_ADD(orderitemsdetail_table.end_date, INTERVAL 7 DAY) < '<CUSTOMER START DATE>'
AND orderitemsdetail_table.start_date > '<CUSTOMER END DATE>')
OR orderitemsdetail_table.id IS NULL

adding row value to total if condition (don't know how to ask this)

I'm running a points system for companies where every employee that works for that company is worth some points.
Every month the points for the companies are calculated.
This works so far, however In the 9th month of this year I would like to give double points for each acquired employee in that month.
I don't know how to do that.
I have this query now:
SELECT company, (employees *2) as "Points"
FROM data
WHERE month = '10'
GROUP BY company
But as you can see I give 2 points for each employee that works for that company in that month.
But for month 9 I want to give double points and add them to current points in current month(10)
I have this SQLfiddle as example: http://sqlfiddle.com/#!9/2cb812/7
Expected result:
company Points
__________________
company 1 26 + (extra points from month 9)
company 2 32 + (extra points from month 9)
company 3 44 + (extra points from month 9)
So it's all about the August/September delta 2018. If you run the query for any month before September 2018 (June 2018, May 2012, whatever), you just want to get the current month's points. If you run the query for any month after August 2018 (December 2018, March 2022, ...) you want the 2018 bonus points added.
Group by company and use conditional aggregation (an aggregation function on a condition) in order to calculate this.
We must look at the requested month (e.g. 10/2018) and August 2018 and September 2018.
SET #yearmonth = '201810';
SELECT
company,
SUM(
CASE WHEN yearmonth = #yearmonth THEN employees * 2 ELSE 0 END +
CASE WHEN #yearmonth >= '201809' AND yearmonth = '201809' THEN employees * 4 ELSE 0 END -
CASE WHEN #yearmonth >= '201809' AND yearmonth = '201808' THEN employees * 4 ELSE 0 END
) AS points
FROM data
WHERE yearmonth in ('201808', '201809', #yearmonth)
GROUP BY company
ORDER BY company;
The WHERE clause is superfluous, as the months are checked inside the SUM function, but it may speed up the query.
Rextester demo: https://rextester.com/ELOWTL44361

Need help for join and some calculations on a MySql insert

I'll try to provide some context so you can understand what I'm trying to achieve here. My company uses open source software to manage the employees leaves (Jorani, feel free to google it :) ).
There are different types of leave (holidays, sick leave, etc.) and we want to calculate the days "not used" from the holidays of 2016 and "copy" them to another type of leave called "Remaining Holidays 2016".
The important tables are:
entitleddays (here you specify how many days of each type you give to an employee)
id employee startdate enddate type days description
661 3 2016-01-01 2017-02-28 1 14.00 Holidays 2016
1296 3 2016-01-01 2016-12-31 4 18.00 Sick leave 2016
leaves (this table has information about the leaves taken by the employees)
id startdate enddate status employee cause duration type
2436 2016-08-01 2016-08-01 3 78 OK from managers 1.00 1
2766 2016-09-05 2016-09-12 3 63 Holidays 6.00 1
So basically we have:
Entitled leaves:
Data stored in the entitleddays table shown above. In our example let's say I have 14 days for my 2016 holidays.
Taken leaves:
Leaves taken by the user, stored in the table called leaves shown above. For our example let's say I took a day off the first of August and 6 days on September.
Available leaves:
Available days are calculated: entitled days minus "taken leaves". For this examplee, 14 entitled days - 7 = 7 days. So I still have seven days available for holidays :D
So my goal is to insert these 7 days for this user as entitled days for the new type: "Remaining days from 2016" and do this for every user. So the solution that comes up to my mind is to do something like this for every user:
INSERT INTO entitleddays (employee, startdate, enddate, type, days, description)
SELECT id, '2017-01-01', '2017-02-31', '8', (entitled holidays for 2016 minus all the taken leaves of this type), 'Remaining holidays from 2016'
FROM users
Where 8 is the new type of leave where I want to copy the days (Remaining holidays from 2016).
For example I can get the taken holidays from 2016 for a specific user doing this:
SELECT SUM(duration)
FROM leaves
WHERE employee=3 AND status=3 AND type=1
Note: Type 1 is the type of leave "Holidays 2016" and status 3 means that the leave request was accepted.
I can probably achieve all of this in a single SQL instruction but it can also be split in more if simpler or easiest to manage/understand.
Many thanks in advance.
This is how you can handle the calculation:
sum the entitleddays in a subquery by grouping the datasets in its table per employee
maybe even group by year? In this case I just filtered for 2016 via WHERE-clause
sum the taken holidays in a subquery, again by grouping per employee
group by year or filter directly for the one you need
join this subquery onto the other resultset of the other query
calculate (entitled days - taken leaves) in the outer query
Query:
SELECT
entitled.employee,
'2017-01-01',
'2017-02-31',
'8' AS type,
entitled.days - takenDays.days,
'Remaining holidays from 2016'
FROM
(
SELECT
employee,
SUM(days) AS days
FROM
entitleddays
WHERE
startdate >= '2016-01-01'
AND type = 1
GROUP BY
employee
) AS entitled
LEFT JOIN (
SELECT
employee,
SUM(duration) AS days
FROM
`leaves`
WHERE
startdate >= '2016-01-01'
AND type = 1
GROUP BY
employee
) AS takenDays ON takenDays.employee = entitled.employee
I am not sure if this is how you want to calculate the sums for the days of entitleddays and taken days. The query just checks if startdate >= '2016-01-01'.
Also you mentioned a table users in your attempt but didn't provide details for the table, so I left it out. I guess you could use it as a basis otherwise. In the current query the grouped result of entitleddays is the basis.
For the insert
INSERT INTO entitleddays (employee, startdate, enddate, type, days, description)
SELECT
entitled.employee,
'2017-01-01',
'2017-02-31',
'8' AS type,
entitled.days - takenDays.days,
'Remaining holidays from 2016'
FROM
(
SELECT
employee,
SUM(days) AS days
FROM
entitleddays
WHERE
startdate >= '2016-01-01'
AND type = 1
GROUP BY
employee
) AS entitled
LEFT JOIN (
SELECT
employee,
SUM(duration) AS days
FROM
`leaves`
WHERE
startdate >= '2016-01-01'
AND type = 1
GROUP BY
employee
) AS takenDays ON takenDays.employee = entitled.employee

SQL - getting totals from a crosstab query

TRANSFORM Count(Research.Patient_ID) AS CountOfPatient_ID
SELECT DateDiff("yyyy",[DOB],Date()) AS [Age Group 22 - 24]
FROM (Research INNER JOIN Demographics ON Research.Patient_ID = Demographics.ID) INNER JOIN [Letter Status] ON Research.Patient_ID = [Letter Status].Patient_ID
WHERE (((DateDiff("yyyy",[DOB],Date())) Between 22 And 24))
GROUP BY DateDiff("yyyy",[DOB],Date())
PIVOT [Letter Status].Letter_Status;
This code lists individual ages, but I want to calculate the Total of all ages that fall within that range. So if there were two 22 year olds, and one 23 year old, the Total would be 3, as opposed to seeing all of their individual ages in the column...
Please help.
Please be sure you understand what you're getting when you use this method to determine a person's age.
DateDiff("yyyy",[DOB],Date())
If DOB = #1987-12-31#, on today's date (#2011-6-16#), DateDiff will give you this as the age:
? DateDiff("yyyy", #1987-12-31#, #2011-6-16#)
24
(And actually for any DOB during 1987, DateDiff with today's date would give you 24 as the "age". Furthermore, for any DOB during 1987, using that method on any day in 2011, you would get 24.)
OTOH, as age is commonly understood, one might say "Nonsense! His birthday is still more than 6 months away. He's only 23 today."
The reason for this discrepancy is that DateDiff("yyyy" only evaluates the year component of two dates. Consider these two dates which are one day apart:
? DateDiff("yyyy",#2010-12-31#,#2011-1-1#)
1
That same thing happens when you use that expression to calculate "age".
To return the age as commonly understood, you can use an expression like this:
? DateDiff("yyyy", #1987-12-31#, Date())+ _
Int( Format(Date(), "mmdd") < Format( #1987-12-31#, "mmdd"))
I copied that expression from the Access Web: Calculate Age of a person. That page includes other approaches for determining age.
None of this matters if, apparently like the OP, you want all DOB in 1987 to be counted as age 24 today, or on any day in 2011.
You need to define the age ranges in a switch statement. To make it easier I've created a inline query to calcuate the age (I'm assuming its on the research table).
TRANSFORM Count(Research.Patient_ID) AS CountOfPatient_ID
SELECT SWITCH (Age <= 22, "Under 22",
Age > 22 and AGE <= 24 , "Between 22 And 24",
Age > 24 and AGE <= 26, "Between 24 And 26",
Age > 26 , "Over 26") as Age_Range
FROM
(Research
INNER JOIN (SELECT ID, DateDiff("yyyy",DOB,Date()) as AGE
FROM Demographics) Demographics
ON Research.Patient_ID = Demographics.ID)
INNER JOIN [Letter Status]
ON Research.Patient_ID = [Letter Status].Patient_ID
GROUP BY AGE
PIVOT [Letter Status].Letter_Status;