powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Структура таблиц(ы) для двустороннего чата
12 сообщений из 12, страница 1 из 1
Структура таблиц(ы) для двустороннего чата
    #38886644
karapetyan_a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вечер добрый.
Нужно хранить двусторонний чат сайта в базе. Вначале подумалось - да тут делать нечего и наваял:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
if object_id('dbo.[Message]') is not null
	drop table dbo.[Message]
go

-- table
create table dbo.[Message](
	Id int identity(1,1) primary key
	, FromUserId int not null -- в реальной базе - FK на таблицю User
	, ToUserId int not null -- в реальной базе - FK на таблицю User
	, [Date] datetime default getdate() not null
	, Body nvarchar(100) not null
	, IsRead bit default 0
)
go

-- data
insert into dbo.[Message](FromUserId, ToUserId, [Date], Body, IsRead)
values
	(1, 2, '2015-01-23 22:00:01', N'privet', 1)
	, (2, 1, '2015-01-23 22:00:02', N'zdorov', 1)
	, (1, 2, '2015-01-23 22:00:03', N'kak ona?', 0)
	, (2, 1, '2015-01-23 22:00:04', N'good', 0)
	, (3, 1, '2015-01-23 21:00:00', N'zanyat?', 0)
	, (4, 5, '2015-01-23 22:00:06', N's fantaziey problemy', 1)
	, (2, 1, '2015-01-23 22:00:07', N's fantaziey problemy', 1)
go



Начал писать запросы - не тут-то было. С этой таблицы мне нужно получать:
1. для notification bar: Id и количество пользователей (не сообщений), от которых имеются непрочитанные сообщения. (получилось вроде нормально)

Код: sql
1.
select m.FromUserId, count(1) as UnreadMessageQty from dbo.[Message] m where m.ToUserId = 1 and m.IsRead = 0 group by m.FromUserId


2. для recent activity list: список последних N пользователей с количеством непрочитанных сообщений с которыми общался, отсортированный по: 1. непрочитанные, 2. последине по дате (как в скайпе recent list) (тут придумывается что-то уродливое)
3. для chat room: список сообщений в хронологическом порядке начиная с конца в количестве N, либо начиная с первого непрочитанного (что больше) (тут тоже ничего хорошего не придумывается)

Вопросы:
1. грамотная ли структура ( с точки зрения постоянных инсертов, и вышесказанных селектов)
2. если да то как-бы похитрее ответить на предыдущие 3 вопроса, учитывая что селекты будут гонятся из EntityFramework.

С уважением. Ашот.

Модератор: Тема перенесена из форума "Microsoft SQL Server".
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38886693
karapetyan_a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
согласен с переносом темы........ сразу не смекнул куда постить.....
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38886769
Serguei
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
karapetyan_a,
Стуктура как структура. Делайте count по нужным условиям. Что смущает-то? Непонятно.
Да! Еще на индексы обратите внимание и все будет отлично!
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38886948
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
karapetyan_a1. грамотная ли структура ( с точки зрения постоянных инсертов, и вышесказанных селектов)
Нет, ведь индексы отсутствуют.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE TABLE [dbo].[Message](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[FromUserId] [int] NOT NULL,
	[ToUserId] [int] NOT NULL,
	[Date] [datetime] NOT NULL DEFAULT getdate(),
	[Body] [nvarchar](100) NOT NULL,
	[IsRead] [bit] NULL DEFAULT 0,
	CONSTRAINT [pk_chart] PRIMARY KEY CLUSTERED (
		[Id] DESC,
		[Date] DESC))

CREATE NONCLUSTERED INDEX [ix_from] ON [dbo].[Message] ([FromUserId] ASC)
GO

CREATE NONCLUSTERED INDEX [ix_to] ON [dbo].[Message] ([ToUserId] ASC) 
GO

CREATE NONCLUSTERED INDEX [ix_unread] ON [dbo].[Message] ([IsRead] DESC)
GO
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887353
karapetyan_a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79,

Может я не четко ворпрос задал.
Понятно что должны быть индексы.
проблема при такой таблице с селектами.
к примеру как выбрать из таблицы список последних сообщений? причем начать надо с первого непрочитанного, либо с последние 10 (смотря что больше).

последние 10 можно легко получить к примеру так:
Код: sql
1.
select top(10) * from dbo.Message m where m.FromUserId = 1 or m.ToUserId = 1 order by m.[Date] desc


а что если первое непрочитанное сообщение не входит в последюю десятку?.......
тут надо найти ид первого непрочитанного сообщения и взять все что больше.......... но хотелось бы как-то похитрее одним селектом все ворпосы решить.
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887411
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не?

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
SELECT * 
FROM dbo.Message m
where 1=1
  AND m.FromUserId = 3
  and m.ToUserId = 1
  AND m.IsRead = 0
UNION 
SELECT TOP 10 * 
FROM dbo.Message m
where 1=1
  AND m.FromUserId = 3
  and m.ToUserId = 1
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887649
karapetyan_a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79,

Спасибо, не знал разницу между UNION и UNION ALL

в итоге вот так вот получилось:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
select * from (
	select * from dbo.Message m where (m.FromUserId = 2 and m.ToUserId = 1 and m.IsRead = 0) 
	union
	select * from (
		select top(10) * from dbo.Message m where (m.FromUserId = 1 and m.ToUserId = 2) or (m.FromUserId = 2 and m.ToUserId = 1) order by m.[Date] desc
	) as top10
) msg
order by msg.[Date] desc



Осталось Recent user list сообразить, ща над этим подумаю.
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887740
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
karapetyan_aОсталось Recent user list сообразить, ща над этим подумаю.
Так наверное
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select FromUserId, LastMoment, count(*) 
from (
	select 
		m.FromUserId,
		MAX(m.Date) over(partition by m.FromUserId) LastMoment
	from dbo.Message m
	where 1=1
	  and ToUserId = @currentUserId
	  and IsRead = 0) t
group by FromUserId, LastMoment
order by FromUserId, LastMoment 
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887761
karapetyan_a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79,

сейчас посмотрю Ваш ответ, а пока вот что натворил для ресент листа:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
select top(10) uc.UserId, min(uc.IsRead) as IsRead
from (	
	select top(20) -- берем в 2 раза больше, чтоб исключить дубликаты
		case when ac.FromUserId = 1 then ac.ToUserId else ac.FromUserId end as UserId
		, case when	ac.ToUserId = 1 then ac.minRead else 1 end as IsRead -- если сообщение не прочитано
		, ac.maxDate
	from (
		select 
			m.FromUserId, m.ToUserId, min(m.IsRead) as minRead, max(m.Date) as maxDate
		from dbo.Message m where m.FromUserId = 1 or m.ToUserId = 1
		group by m.FromUserId, m.ToUserId
	) ac -- all contacts
	order by ac.minRead, ac.maxDate desc
) uc -- unique contacts
group by uc.UserId
order by min(uc.IsRead), max(uc.maxDate)



правда пришлось IsRead bit поменять на tinyint иначе мин/макс не работал по нему
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887766
karapetyan_a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79karapetyan_aОсталось Recent user list сообразить, ща над этим подумаю.
Так наверное
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select FromUserId, LastMoment, count(*) 
from (
	select 
		m.FromUserId,
		MAX(m.Date) over(partition by m.FromUserId) LastMoment
	from dbo.Message m
	where 1=1
	  and ToUserId = @currentUserId
	  and IsRead = 0) t
group by FromUserId, LastMoment
order by FromUserId, LastMoment 



проверил, получаю только последние не прочитанные Юзером, а задача стоит, Все - с кем юзер общался, не важно он или ему писали.
(кстати слова "over(partition by m.FromUserId)" для меня не понятны, не знакомы и потому страшны....... надо в мсдн лезть :)
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887778
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
karapetyan_a2. для recent activity list: список последних N пользователей с количеством непрочитанных сообщений с которыми общался
Как было, так и написал. Нужно все, убираем из where isread=0 и все.
Ну и "and (ToUserId = @currentUserId or FromUserId = @currentUserId)"

MAX () over () - это найти максимальную дату для каждого FromUserId в выборке
...
Рейтинг: 0 / 0
Структура таблиц(ы) для двустороннего чата
    #38887812
karapetyan_a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arm79,

Спасибо большое, помогли........ по любому уже вижу куда копать.

Вопрос вроде ясен:)
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Структура таблиц(ы) для двустороннего чата
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]