Selectively ignoring tuples from a table - mysql

The problem that we are tackling with a data mining application is best described with an illustrative example.
There is a sample table myTable, which is defined as follows:
CREATE TABLE myTable
(
id INT UNSIGNED AUTO_INCREMENT,
colA VARCHAR(8),
colB VARCHAR(12),
revFlag CHAR(8), -- 'REVISED' or any other value, including NULL
PRIMARY KEY(id)
);
Any tuple with a revFlag value of REVISED takes precedence over any other tuple with the same value for colA, as long as the revFlag value of the latter tuple is not REVISED. In other words when we select rows from the table we skip all rows for which the revFlag value is not REVISED and there exists a row with the same value for colA for which the revFlag value is REVISED.
We populate the table as follows:
INSERT INTO myTable(colA, colB) VALUES ('XSR0KA3V', 'OLD-O7RAR81X'),
('4F2JG71O', 'OLD-E71BE63L'), ('MML3HN48', 'OLD-B02PFB63'),
('5H0MWVSB', 'OLD-V70XLGHT'), ('JW73ZX0J', 'OLD-KME1GXQF'),
('XZV0EY0G', 'OLD-N06BURDF'), ('9HBQZ88V', 'OLD-76HSPUAL'),
('YI5AT6G4', 'OLD-X8KAWD7Z');
INSERT INTO myTable(colA, colB, revFlag) VALUES
('XSR0KA3V', 'NEW-O7RAR81X', 'REVISED'),
('MML3HN48', 'NEW-B02PFB63', 'REVISED'),
('9HBQZ88V', 'NEW-76HSPUAL', 'REVISED'),
('YI5AT6G4', 'NEW-X8KAWD7Z', 'XYZ'),
('Z8H2B5KY', '3RINJV0K', 'REVISED');
Naturally SELECT * FROM myTable yields the following:
+----+----------+--------------+---------+
| id | colA | colB | revFlag |
+----+----------+--------------+---------+
| 1 | XSR0KA3V | OLD-O7RAR81X | NULL |
| 2 | 4F2JG71O | OLD-E71BE63L | NULL |
| 3 | MML3HN48 | OLD-B02PFB63 | NULL |
| 4 | 5H0MWVSB | OLD-V70XLGHT | NULL |
| 5 | JW73ZX0J | OLD-KME1GXQF | NULL |
| 6 | XZV0EY0G | OLD-N06BURDF | NULL |
| 7 | 9HBQZ88V | OLD-76HSPUAL | NULL |
| 8 | YI5AT6G4 | OLD-X8KAWD7Z | NULL |
| 9 | XSR0KA3V | NEW-O7RAR81X | REVISED |
| 10 | MML3HN48 | NEW-B02PFB63 | REVISED |
| 11 | 9HBQZ88V | NEW-76HSPUAL | REVISED |
| 12 | YI5AT6G4 | NEW-X8KAWD7Z | XYZ |
| 13 | Z8H2B5KY | 3RINJV0K | REVISED |
+----+----------+--------------+---------+
We would like to design a query that does not return any tuples that are REVISED by other tuples. In our case the output should look like this:
+----+----------+--------------+---------+
| id | colA | colB | revFlag |
+----+----------+--------------+---------+
| 2 | 4F2JG71O | OLD-E71BE63L | NULL |
| 4 | 5H0MWVSB | OLD-V70XLGHT | NULL |
| 5 | JW73ZX0J | OLD-KME1GXQF | NULL |
| 6 | XZV0EY0G | OLD-N06BURDF | NULL |
| 8 | YI5AT6G4 | OLD-X8KAWD7Z | NULL |
| 9 | XSR0KA3V | NEW-O7RAR81X | REVISED |
| 10 | MML3HN48 | NEW-B02PFB63 | REVISED |
| 11 | 9HBQZ88V | NEW-76HSPUAL | REVISED |
| 12 | YI5AT6G4 | NEW-X8KAWD7Z | XYZ |
| 13 | Z8H2B5KY | 3RINJV0K | REVISED |
+----+----------+--------------+---------+

You can use a NOT EXISTS clause to filter out all rows for which another row exists which has the same colA value and revFlag = 'REVISED':
SELECT *
FROM myTable t1
WHERE NOT EXISTS (
SELECT *
FROM myTable t2
WHERE t2.id != t1.id AND t2.colA = t1.colA AND t2.revFlag = 'REVISED'
)
Output:
id colA colB revFlag
2 4F2JG71O OLD-E71BE63L (null)
4 5H0MWVSB OLD-V70XLGHT (null)
5 JW73ZX0J OLD-KME1GXQF (null)
6 XZV0EY0G OLD-N06BURDF (null)
8 YI5AT6G4 OLD-X8KAWD7Z (null)
9 XSR0KA3V NEW-O7RAR81X REVISED
10 MML3HN48 NEW-B02PFB63 REVISED
11 9HBQZ88V NEW-76HSPUAL REVISED
12 YI5AT6G4 NEW-X8KAWD7Z XYZ
13 Z8H2B5KY 3RINJV0K REVISED
Demo on dbfiddle

SELECT stuff
FROM somewhere x
LEFT
JOIN somewhere y
ON y.thing = x.thing
AND y.otherthing = x.otherthing
AND y.anotherthing > x.anotherthing
AND y.whatever = 'some value'
WHERE y.anotherthing .... ;

You could use the IN Clause
Schema (MySQL v8.0)
CREATE TABLE table1 (
`id` INTEGER,
`colA` VARCHAR(8),
`colB` VARCHAR(12),
`revFlag` VARCHAR(7)
);
INSERT INTO table1
(`id`, `colA`, `colB`, `revFlag`)
VALUES
('1', 'XSR0KA3V', 'OLD-O7RAR81X', NULL),
('2', '4F2JG71O', 'OLD-E71BE63L', NULL),
('3', 'MML3HN48', 'OLD-B02PFB63', NULL),
('4', '5H0MWVSB', 'OLD-V70XLGHT', NULL),
('5', 'JW73ZX0J', 'OLD-KME1GXQF', NULL),
('6', 'XZV0EY0G', 'OLD-N06BURDF', NULL),
('7', '9HBQZ88V', 'OLD-76HSPUAL', NULL),
('8', 'YI5AT6G4', 'OLD-X8KAWD7Z', NULL),
('9', 'XSR0KA3V', 'NEW-O7RAR81X', 'REVISED'),
('18', 'XSR0KA3V', 'NEW-O7RAR81X', 'ZRNTR'),
('10', 'MML3HN48', 'NEW-B02PFB63', 'REVISED'),
('11', '9HBQZ88V', 'NEW-76HSPUAL', 'REVISED'),
('12', 'YI5AT6G4', 'NEW-X8KAWD7Z', 'XYZ'),
('13', 'Z8H2B5KY', '3RINJV0K', 'REVISED');
Query #1
SELECT
`id`, `colA`, `colB`, `revFlag`
FROM
table1 t1
WHERE
(`colA` , IFNULL(`revFlag`,0)) IN
(SELECT
`colA`, `revFlag`
FROM
table1
WHERE
`revFlag` = 'REVISED' UNION SELECT
`colA`, IFNULL(MAX(`revFlag`),0)
FROM
table1
WHERE
`colA` NOT IN (SELECT
`colA`
FROM
table1
WHERE
`revFlag` = 'REVISED')
GROUP BY `colA`)
ORDER BY id;
id
colA
colB
revFlag
2
4F2JG71O
OLD-E71BE63L
4
5H0MWVSB
OLD-V70XLGHT
5
JW73ZX0J
OLD-KME1GXQF
6
XZV0EY0G
OLD-N06BURDF
9
XSR0KA3V
NEW-O7RAR81X
REVISED
10
MML3HN48
NEW-B02PFB63
REVISED
11
9HBQZ88V
NEW-76HSPUAL
REVISED
12
YI5AT6G4
NEW-X8KAWD7Z
XYZ
13
Z8H2B5KY
3RINJV0K
REVISED
View on DB Fiddle

Related

Sort mysql result by two column, but with a “holed” column

I have the following initial situation:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
| 0 | NULL |
| 1 | 6 |
| 2 | NULL |
| 3 | 1 |
| 4 | NULL |
| 5 | NULL |
| 6 | 2 |
+------------+-------------+
You could generate this table by the following schema:
CREATE TABLE two_column_order (
legacyRank VARCHAR(45),
forcedRank VARCHAR(45)
);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (5, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (6, 2);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (7, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (0, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (1, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (2, 6);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (3, NULL);
INSERT INTO two_column_order (legacyRank, forcedRank)
VALUES (4, 1);
SELECT * FROM two_column_order
order by
CASE when `forcedRank` <> NULL THEN `forcedRank`
ELSE `legacyRank`
END
The goal is to put each line with no-NULL forcedRank column in the accurate position mentioned in this forcedRank column. The expected rendering is like:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
0 | 0 | NULL |
1 | 3 | 1 |
2 | 6 | 2 |
3 | 2 | NULL |
4 | 4 | NULL |
5 | 5 | NULL |
6 | 6 | 6 |
+------------+-------------+
As you see, each line take the position ordered by the forcedRank column if not NULL. When the the NULL rows still sorted by the legacyRank column in the positions leaved unoccupied by the non-NULL rows, but never shift the forced rows.
In this order, I tried to use the CASE WHEN syntax inside the ORDER BY like this:
SELECT * FROM two_column_order
order by
CASE WHEN (`forcedRank` is NULL ) THEN `legacyRank`
END ,
-`forcedRank` DESC,
`legacyRank`
But the result doesn’t really feat my expectations:
+------------+-------------+
| legacyRank | forcedRank |
+------------+-------------+
| 3 | 1 |
| 6 | 2 |
| 6 | 6 |
| 0 | NULL |
| 2 | NULL |
| 4 | NULL |
| 5 | NULL |
+------------+-------------+
So how can I make the legacyRank column get order beyond the forcedrank rows without shift them?
NULL can't tbe comapred like that you need to use ISor in your case IS NOT
SELECT * FROM two_column_order
order by
CASE when `forcedRank` IS NOT NULL THEN `forcedRank`
ELSE `legacyRank`
END
legacyRank
forcedRank
0
null
1
null
4
1
6
2
3
null
5
null
2
6
7
null
fiddle
As the first answer won't give you the correct answer.
i have changed the order by adding a decimal point to the original number so that it will be bigger than the new forced rank.
it will keep the order and a the forced number is smaller then the legayrank, it get you follwoing result
SELECT * FROM two_column_order
order by
CASE when `forcedRank` IS NOT NULL THEN `forcedRank`
ELSE `legacyRank` + .1
END
legacyRank
forcedRank
0
null
4
1
1
null
6
2
3
null
5
null
2
6
7
null
fiddle

How to extract different json elements from the same table in SQL query?

I am querying from a table with the following format:
id|provider|score
--------------------------------
1 | att | '{"attscore":300}'
1 | verizon | '{"verizonscore":299}'
2 | att | '{"attscore":200}'
3 | verizon | '{"verizonscore":155}'
I am trying to get a table that looks like the following:
id|attscore|verizonscore
-------------------------
1 | 300 | 299
2 | 200 | null
3 | null | 155
Note that used to json in sql
CREATE TABLE table1 (
`id` INTEGER,
`provider` VARCHAR(7),
`score` VARCHAR(22)
);
INSERT INTO table1
(`id`, `provider`, `score`)
VALUES
('1', 'att', '{"attscore":300}'),
('1', 'verizon', '{"verizonscore":299}'),
('2', 'att', '{"attscore":200}'),
('3', 'verizon', '{"verizonscore":155}');
SELECT
id,
GROUP_CONCAT(CASE WHEN provider = 'att' THEN `score`->"$.attscore" ELSe NULL END) attscore
,GROUP_CONCAT(CASE WHEN provider = 'verizon' THEN `score`->"$.verizonscore" ELSe NULL END) verizonscore
FROM table1
GROUP BY id
id | attscore | verizonscore
-: | :------- | :-----------
1 | 300 | 299
2 | 200 | null
3 | null | 155
db<>fiddle here
This works with a fixed number of column quite well, if you have much more of these you need to do something like this

how to create a counting column for a particular item

I have the following schema (mysql)
create table test(
userid int(11) not null,
item varchar(15),
bookid int(11));
insert into test values ('1','journal',NULL);
insert into test values ('1','journal',NULL);
insert into test values ('1','book',NULL);
insert into test values ('2','book',NULL);
insert into test values ('2','journal',NULL);
insert into test values ('1','book',NULL);
insert into test values ('2','journal',NULL);
insert into test values ('3','book',NULL);
insert into test values ('1','book',NULL);
insert into test values ('1','journal',NULL);
insert into test values ('3','journal',NULL);
insert into test values ('1','journal',NULL);
insert into test values ('2','journal',NULL);
insert into test values ('2','book',NULL);
insert into test values ('2','journal',NULL);
insert into test values ('1','journal',NULL);
insert into test values ('3','book',NULL);
insert into test values ('3','book',NULL);
insert into test values ('3','book',NULL);
insert into test values ('3','book',NULL);
whenever there is a book, I'm trying assign an auto increment beginning with 1 in the bookid column. For each user, the numbering begins again from 1. I know a way this can be done by creating a separate table. Is there a way I can avoid that and accomplish that using some sort of update query in this very table and update the column bookid? I am trying to get output similar to the following:
userid,item,bookid
'1','journal',NULL
'1','journal',NULL
'1','book',1
'2','book',1
'2','journal',NULL
'1','book',2
'2','journal',NULL
'3','book',1
'1','book',3
'1','journal',NULL
'3','journal',NULL
'1','journal',NULL
'2','journal',NULL
'2','book',2
'2','journal',NULL
'1','journal',NULL
'3','book',2
'3','book',3
'3','book',4
'3','book',5
I appreciate if someone could guide me on how to accomplish this?
Here's one idea...
drop table if exists test;
create table test
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,userid int not null
,item varchar(15) NOT NULL
);
insert into test (userid,item) values
(1,'journal')
,(1,'journal')
,(1,'book')
,(2,'book')
,(2,'journal')
,(1,'book')
,(2,'journal')
,(3,'book')
,(1,'book')
,(1,'journal')
,(3,'journal')
,(1,'journal')
,(2,'journal')
,(2,'book')
,(2,'journal')
,(1,'journal')
,(3,'book')
,(3,'book')
,(3,'book')
,(3,'book');
SELECT x.*
, COUNT(*) rank
FROM test x
JOIN test y
ON y.userid = x.userid
AND y.item = x.item
AND y.id <= x.id
GROUP
BY id
ORDER
BY userid
, item
, rank;
+----+--------+---------+------+
| id | userid | item | rank |
+----+--------+---------+------+
| 3 | 1 | book | 1 |
| 6 | 1 | book | 2 |
| 9 | 1 | book | 3 |
| 1 | 1 | journal | 1 |
| 2 | 1 | journal | 2 |
| 10 | 1 | journal | 3 |
| 12 | 1 | journal | 4 |
| 16 | 1 | journal | 5 |
| 4 | 2 | book | 1 |
| 14 | 2 | book | 2 |
| 5 | 2 | journal | 1 |
| 7 | 2 | journal | 2 |
| 13 | 2 | journal | 3 |
| 15 | 2 | journal | 4 |
| 8 | 3 | book | 1 |
| 17 | 3 | book | 2 |
| 18 | 3 | book | 3 |
| 19 | 3 | book | 4 |
| 20 | 3 | book | 5 |
| 11 | 3 | journal | 1 |
+----+--------+---------+------+
Note that MyISAM actually lets you use a composite PK in which part of that composite is an auto-incrementing id, but InnoDB prohinits this.
On larger datasets a query along these lines will likely be far more efficient...
SELECT id
, userid
, item
, IF(#userid=userid,IF(#item=item,#i:=#i+1,#i:=1),#i:=1) rank
, #userid := userid
, #item := item
FROM test
, (SELECT #userid = NULL,#item:='',#i:=1) vars
ORDER
BY userid,item,id;

Update the next row of the target row in MySQL

Suppose I have a table that tracks if a payment is missed like this:
+----+---------+------------+------------+---------+--------+
| id | loan_id | amount_due | due_at | paid_at | missed |
+----+---------+------------+------------+---------+--------+
| 1 | 1 | 100 | 2013-08-17 | NULL | NULL |
| 5 | 1 | 100 | 2013-09-17 | NULL | NULL |
| 7 | 1 | 100 | 2013-10-17 | NULL | NULL |
+----+---------+------------+------------+---------+--------+
And, for example, I ran a query that checks if a payment is missed like this:
UPDATE loan_payments
SET missed = 1
WHERE DATEDIFF(NOW(), due_at) >= 10
AND paid_at IS NULL
Then suppose that the row with id = 1 gets affected. I want the amount_due of row with id = 1 be added to the amount_due of the next row so the table would look like this:
+----+---------+------------+------------+---------+--------+
| id | loan_id | amount_due | due_at | paid_at | missed |
+----+---------+------------+------------+---------+--------+
| 1 | 1 | 100 | 2013-08-17 | NULL | 1 |
| 5 | 1 | 200 | 2013-09-17 | NULL | NULL |
| 7 | 1 | 100 | 2013-10-17 | NULL | NULL |
+----+---------+------------+------------+---------+--------+
Any advice on how to do it?
Thanks
Take a look at this :
SQL Fiddle
MySQL 5.5.32 Schema Setup:
CREATE TABLE loan_payments
(`id` int, `loan_id` int, `amount_due` int,
`due_at` varchar(10), `paid_at` varchar(4), `missed` varchar(4))
;
INSERT INTO loan_payments
(`id`, `loan_id`, `amount_due`, `due_at`, `paid_at`, `missed`)
VALUES
(1, 1, 100, '2013-09-17', NULL, NULL),
(3, 2, 100, '2013-09-17', NULL, NULL),
(5, 1, 100, '2013-10-17', NULL, NULL),
(7, 1, 100, '2013-11-17', NULL, NULL)
;
UPDATE loan_payments AS l
LEFT OUTER JOIN (SELECT loan_id, MIN(ID) AS ID
FROM loan_payments
WHERE DATEDIFF(NOW(), due_at) < 0
GROUP BY loan_id) AS l2 ON l.loan_id = l2.loan_id
LEFT OUTER JOIN loan_payments AS l3 ON l2.id = l3.id
SET l.missed = 1, l3.amount_due = l3.amount_due + l.amount_due
WHERE DATEDIFF(NOW(), l.due_at) >= 10
AND l.paid_at IS NULL
;
Query 1:
SELECT *
FROM loan_payments
Results:
| ID | LOAN_ID | AMOUNT_DUE | DUE_AT | PAID_AT | MISSED |
|----|---------|------------|------------|---------|--------|
| 1 | 1 | 100 | 2013-09-17 | (null) | 1 |
| 3 | 2 | 100 | 2013-09-17 | (null) | 1 |
| 5 | 1 | 200 | 2013-10-17 | (null) | (null) |
| 7 | 1 | 100 | 2013-11-17 | (null) | (null) |
Unfortunately I don't have time at the moment to write out full-blown SQL, but here's the psuedocode I think you need to implement:
select all DISTINCT loan_id from table loan_payments
for each loan_id:
set missed = 1 for all outstanding payments for loan_id (as determined by date)
select the sum of all outstanding payments for loan_id
add this sum to the amount_due for the loan's next due date after today
Refer to this for how to loop using pure MySQL: http://dev.mysql.com/doc/refman/5.7/en/cursors.html
I fixed my own problem by adding a missed_at field. I put the current timestamp ($now) in a variable before I update the first row to missed = 1 and missed_at = $now then I ran this query to update the next row's amount_due:
UPDATE loan_payments lp1 JOIN loan_payments lp2 ON lp1.due_at > lp2.due_at
SET lp1.amount_due = lp2.amount_due + lp1.amount_due
WHERE lp2.missed_at = $now AND DATEDIFF(lp1.due_at, lp2.due_at) <= DAYOFMONTH(LAST_DAY(lp1.due_at))
I wish I could use just use LIMIT 1 to that query but it turns out that it's not possible for an UPDATE query with a JOIN.
So all in all, I used two queries to achieve what I want. It did the trick.
Please advise if you have better solutions.
Thanks!

MySQL - Tricky LIMIT for each WHERE_IN problem

I am looking to do the following (see pseudo code); I want to select 4 rows for each gd.id (7, 11 or 9). I've incorrectly use limit because that only brings up 4 rows in total. Anyone have an idea on how to change this query to accomplish my goal?
SELECT gd.gid, gd.aid, li.ads, li.til
FROM gd
JOIN li ON li.a_id = gd.aid
WHERE gd.gid
IN (
'7', '11', '9'
)
ORDER BY li.timestamp DESC
LIMIT 4 #FOR EACH ;-)
Thank you!
Ice
p.s. Maybe sometype of group_by?
Okay I'm posting this second answer now that I understand the relationship between your tables.
CREATE TABLE gd (
aid INT AUTO_INCREMENT PRIMARY KEY,
gid INT
);
INSERT INTO gd (gid) VALUES
(7), (7), (7), -- fewer than four rows
(9), (9), (9), (9), -- exactly four rows
(11), (11), (11), (11), (11); -- greater than four rows
CREATE TABLE li (
a_id INT AUTO_INCREMENT PRIMARY KEY,
ads VARCHAR(10),
til VARCHAR(10),
`timestamp` TIMESTAMP
);
INSERT INTO li (ads, til, `timestamp`) VALUES
('foo1', 'bar1', '2008-01-01'),
('foo2', 'bar2', '2008-02-01'),
('foo3', 'bar3', '2008-03-01'),
('foo4', 'bar4', '2008-04-01'),
('foo5', 'bar5', '2008-05-01'),
('foo6', 'bar6', '2008-06-01'),
('foo7', 'bar7', '2008-07-01'),
('foo8', 'bar8', '2008-08-01'),
('foo9', 'bar9', '2008-09-01'),
('foo10', 'bar10', '2008-10-01'),
('foo11', 'bar11', '2008-11-01'),
('foo12', 'bar12', '2008-12-01');
So you want the top four rows per value of gd.gid, depending on the timestamp value in the associated table li.
SELECT g1.gid, g1.aid, l1.ads, l1.til, l1.`timestamp`
FROM gd AS g1
INNER JOIN li AS l1 ON (g1.aid = l1.a_id)
LEFT OUTER JOIN (
gd AS g2 INNER JOIN li AS l2 ON (g2.aid = l2.a_id)
) ON (g1.gid = g2.gid AND l1.`timestamp` <= l2.`timestamp`)
WHERE g1.gid IN ('7', '11', '9')
GROUP BY g1.aid
HAVING COUNT(*) <= 4
ORDER BY g1.gid ASC, l1.`timestamp` DESC;
The output is the following:
+------+-----+-------+-------+---------------------+
| gid | aid | ads | til | timestamp |
+------+-----+-------+-------+---------------------+
| 7 | 3 | foo3 | bar3 | 2008-03-01 00:00:00 |
| 7 | 2 | foo2 | bar2 | 2008-02-01 00:00:00 |
| 7 | 1 | foo1 | bar1 | 2008-01-01 00:00:00 |
| 9 | 7 | foo7 | bar7 | 2008-07-01 00:00:00 |
| 9 | 6 | foo6 | bar6 | 2008-06-01 00:00:00 |
| 9 | 5 | foo5 | bar5 | 2008-05-01 00:00:00 |
| 9 | 4 | foo4 | bar4 | 2008-04-01 00:00:00 |
| 11 | 12 | foo12 | bar12 | 2008-12-01 00:00:00 |
| 11 | 11 | foo11 | bar11 | 2008-11-01 00:00:00 |
| 11 | 10 | foo10 | bar10 | 2008-10-01 00:00:00 |
| 11 | 9 | foo9 | bar9 | 2008-09-01 00:00:00 |
+------+-----+-------+-------+---------------------+
the usual approach is:
(SELECT * FROM table WHERE key=X LIMIT 4)
UNION ALL
(SELECT * FROM table WHERE key=Y LIMIT 4)
UNION ALL
(SELECT * FROM table WHERE key=Z LIMIT 4)
ORDER BY ... LIMIT ...
do note, it will materialize each subselect in the temptable, so isn't very efficient if your outer LIMIT is low, and internal ones are high.