We have been using pretty reliably this one from Admins United discord:
create table if not exists ListOfThralls (id bigint unique null, class text null, name text null, hexId text null, x text null, y text null, z text null, ownerId bigint null, owningPlayer text null, owningClan text null, playerLastOnline text null, TeleportLocation text null);
insert or ignore into ListOfThralls (id) select distinct object_id from properties where name like 'BP_Thrall%' and name like '%OwnerUniqueID';
update ListOfThralls as l set class = (select substr(substr((value),13),0,length(substr((value),13))-8) from properties p where object_id = id and p.name like '%ThrallInfo');
update ListOfThralls as l set name = (select substr(substr((value),22),0,length(substr((value),22))) from properties p where object_id = id and (p.name like '%ThrallName' or p.name like '%PetName'));
update ListOfThralls as l set hexId = (select substr(hex(value),-12,2) || substr(hex(value),-14,2) || substr(hex(value),-16,2) as hexId from properties p where p.object_id = l.id and p.name like '%OwnerUniqueID%' limit 1);
update ListOfThralls as l set x = (select x from actor_position a where a.id = l.id);
update ListOfThralls as l set y = (select y from actor_position a where a.id = l.id);
update ListOfThralls as l set z = (select z from actor_position a where a.id = l.id);
update ListOfThralls as l set ownerId = (
WITH RECURSIVE
unhex(str, val, weight) AS (
select l.hexId, 0, 1
UNION ALL
SELECT
substr(str, 1, length(str) - 1),
val + (instr('0123456789ABCDEF', substr(str, length(str), 1)) - 1) * weight,
weight * 16
FROM unhex WHERE length(str) > 0
)
SELECT val FROM unhex order by weight desc limit 1
);
update ListOfThralls as l set owningPlayer = (select char_name from characters c where c.id = l.ownerId);
update ListOfThralls as l set owningClan = (select name from guilds g where g.guildId = l.ownerId);
update ListOfThralls as l set playerLastOnline = (select datetime(c.lastTimeOnline, 'unixepoch') as playerLastOnline from characters c where c.id = l.ownerId
union all
select datetime(c.lastTimeOnline, 'unixepoch') as clanLastOnline from characters c where c.guild = l.ownerId order by clanLastOnline desc limit 1);
select id as ThrallId, class as ThrallType, name, owningPlayer, owningClan, playerLastOnline, 'TeleportPlayerExact ' || x || ' ' || y || ' ' || z as TeleportLocation from ListOfThralls order by playerLastOnline asc, owningPlayer asc, owningClan asc;
--drop table ListOfThralls